Как заменить любой символ в строке, имеющей значение ASCII, большее 127 в Oracle [duplicate]

Хотя использование для операторов star / splat было расширенным в Python 3, мне нравится следующая таблица, относящаяся к использованию этих операторов с функциями . Оператор (ы) splat может использоваться как в функции construction , так и в функции call :

            In function *construction*      In function *call*
=======================================================================
          |  def f(*args):                 |  def f(a, b):
*args     |      for arg in args:          |      return a + b
          |          print(arg)            |  args = (1, 2)
          |  f(1, 2)                       |  f(*args)
----------|--------------------------------|---------------------------
          |  def f(a, b):                  |  def f(a, b):
**kwargs  |      return a + b              |      return a + b
          |  def g(**kwargs):              |  kwargs = dict(a=1, b=2)
          |      return f(**kwargs)        |  f(**kwargs)
          |  g(a=1, b=2)                   |
-----------------------------------------------------------------------

Это действительно просто обобщает Lorin Hochstein's отвечает , но я считаю это полезным.

21
задан FerranB 12 February 2010 в 23:23
поделиться

15 ответов

В однобайтовой ASCII-совместимой кодировке (например, Latin-1) символы ASCII являются просто байтами в диапазоне от 0 до 127. Таким образом, вы можете использовать что-то вроде [\x80-\xFF] для обнаружения символов, отличных от ASCII.

6
ответ дан Max Shawabkeh 25 August 2018 в 20:11
поделиться
  • 1
    Я попытался использовать шестнадцатеричные коды, как было предложено: - regexp_replace (column, '[\ x00- \ xFF]', '') Ничего не удаляет заглавными буквами - у меня что-то скрывается или есть что-то еще, что мне нужно сделать ? – Paul Gilfedder 10 February 2010 в 14:19
  • 2
    Я сталкиваюсь с проблемами, использующими ваше решение. Этот ответ был принят, поэтому я считаю, что это не совсем неправильно, но 1.) oracle не поддерживает синтаксис регулярного выражения для указания кодовых точек / символов по их шестнадцатеричному представлению (т. Е. '\ X80'); вместо этого вы должны сами указывать сами символы (однако шаблон регулярного выражения представляет собой строковое выражение, поэтому вы можете использовать что-то вроде '['||chr(128)||'-'||chr(255)||']'), 2.) попытка заменить все символы в '['||chr(32)||'-'||chr(127)||']' приводит к ошибке ora-12728 (недействительно диапазон в регулярном выражении). my db charset - al32utf8. есть идеи? – collapsar 27 March 2015 в 13:56
  • 3
    Я должен добавить, что 1.) БД - это oracle 11.2.0.3.0, 2.) диапазоны 32-122, 32-255 не вызывают ошибки, но 3.) применяются к строке, состоящей из букв алфавита смешанного алфавита и цифры показывают обратное поведение к ожидаемому (т. е. REGEXP_REPLACE ( 'abc', '['||chr(32)||'-'||chr(128)||']' , '_' ) производит abc, а REGEXP_REPLACE ( 'abc', '[^'||chr(32)||'-'||chr(128)||']' , '_' ) возвращает ___). – collapsar 27 March 2015 в 14:01

Спасибо, это сработало для моих целей. Кстати, в приведенном выше примере отсутствует одиночная кавычка.

REGEXP_REPLACE (COLUMN, '[^' || CHR (32) || '-' || CHR (127) || '] ',' '))

Я использовал его в функции переноса слов. Иногда во входящем тексте была встроена новая строка / NL / CHR (10) / 0A, которая была беспорядочной.

0
ответ дан allen 25 August 2018 в 20:11
поделиться

Я немного опоздал с ответом на этот вопрос, но у меня была такая же проблема в последнее время (люди вырезают и вставляют всевозможные вещи в строку, и мы не всегда знаем, что это такое). Ниже приведен простой подход с использованием белого символа:

SELECT est.clients_ref
  ,TRANSLATE (
              est.clients_ref
             ,   'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890#$%^&*()_+-={}|[]:";<>?,./'
              || REPLACE (
                          TRANSLATE (
                                     est.clients_ref
                                    ,'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890#$%^&*()_+-={}|[]:";<>?,./'
                                    ,'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
                                    )
                         ,'~'
                         )
             ,'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890#$%^&*()_+-={}|[]:";<>?,./'
             )
      clean_ref

FROM edms_staging_table est

-3
ответ дан Bowdzone 25 August 2018 в 20:11
поделиться

Ответ, данный Франциско Хайозом, является лучшим. Не используйте функции pl / sql, если sql может сделать это за вас.

Вот простой тест в Oracle 11.2.03

select s
     , regexp_replace(s,'[^'||chr(1)||'-'||chr(127)||']','') "rep ^1-127"
     , dump(regexp_replace(s,'['||chr(127)||'-'||chr(225)||']','')) "rep 127-255"
from (
select listagg(c, '') within group (order by c) s
  from (select 127+level l,chr(127+level) c from dual connect by level < 129))

И «rep 127-255» является

Typ = 1 Len = 30: 226,227,228,229,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,244,251,252,253,254,255

, то есть по какой-то причине эта версия Oracle не заменяет char (226) и выше. Используя '[' || chr (127) || '-' || chr (225) || ']' дает желаемый результат. Если вам нужно заменить другие символы, просто добавьте их в регулярное выражение выше или используйте вложенную замену | regexp_replace, если замена отличается от «'(пустая строка).

0
ответ дан demongolem 25 August 2018 в 20:11
поделиться

Выбор может выглядеть следующим образом:

select nvalue from table
where length(asciistr(nvalue))!=length(nvalue)  
order by nvalue;
3
ответ дан EL Yusubov 25 August 2018 в 20:11
поделиться
  • 1
    Хорошая идея, но с этим вы фактически идентифицируете поля, имеющие данные, где размер в байтах не совпадает с количеством символов, представленных ими. – lucabelluccini 12 August 2014 в 16:11
  • 2
    Также неверно возвращает & quot; \ & quot; ключ как символ не ascii. – Mike Samaras 24 August 2018 в 11:09

Обратите внимание, что всякий раз, когда вы используете

regexp_like(column, '[A-Z]')

, механизм regexp Oracle будет соответствовать определенным символам из диапазона Latin-1: это относится ко всем символам, которые похожи на символы ASCII, такие как Ä-> A, Ö-> O, Ü-> U и т. Д., Так что [AZ] не то, что вы знаете из других сред, таких как, например, Perl.

Вместо того, чтобы возиться с регулярными выражениями, попробуйте изменить для тип данных NVARCHAR2 до обновления набора символов.

Другой подход: вместо того, чтобы отсекать часть содержимого полей, вы можете попробовать функцию SOUNDEX, если ваша база данных содержит только европейские символы (например, Latin-1) , Или вы просто пишете функцию, которая переводит символы из диапазона Latin-1 в аналогичные символы ASCII, такие как

  • å => a
  • ä => a
  • ö => o

, конечно, только для текстовых блоков, превышающих 4000 байт, при преобразовании в UTF-8.

0
ответ дан elwood 25 August 2018 в 20:11
поделиться

Я бы не рекомендовал его для производственного кода, но он имеет смысл и, похоже, работает:

SELECT REGEXP_REPLACE(COLUMN,'[^' || CHR(1) || '-' || CHR(127) || '],'')
9
ответ дан Francisco Hayoz 25 August 2018 в 20:11
поделиться
  • 1
    Обратите внимание, что обычно вы начинаете с 32 вместо 1, так как это первый печатный символ ascii. Остальные - это управляющие символы, которые были бы странными внутри текстовых столбцов (даже более странных, чем & gt; 127, я бы сказал). Но технически ответ правильный, это обнаружило бы символы не-ascii, учитывая исходный 7-разрядный стандарт ascii. – Luc 5 January 2014 в 06:19

У меня была аналогичная проблема, и я писал о ней здесь . Я начал с регулярного выражения для альфа-чисел, а затем добавил в несколько основных символов пунктуации, которые мне понравились:

select dump(a,1016), a, b
from
 (select regexp_replace(COLUMN,'[[:alnum:]/''%()> -.:=;[]','') a,
         COLUMN b
  from TABLE)
where a is not null
order by a;

Я использовал дамп с вариантом 1016, чтобы выдать шестнадцатеричные символы, которые я хотел заменить, может затем пользователь в utl_raw.cast_to_varchar2.

2
ответ дан Gary Myers 25 August 2018 в 20:11
поделиться

Попробуйте следующее:

-- To detect
select 1 from dual
where regexp_like(trim('xx test text æ¸¬è© ¦ “xmx” number²'),'['||chr(128)||'-'||chr(255)||']','in')

-- To strip out
select regexp_replace(trim('xx test text æ¸¬è© ¦ “xmxmx” number²'),'['||chr(128)||'-'||chr(255)||']','',1,0,'in')
from dual
2
ответ дан jadarnel27 25 August 2018 в 20:11
поделиться

Вероятно, существует более прямой способ использования регулярных выражений. Если повезет, кто-то еще это предоставит. Но вот то, что я сделал бы, не прибегая к руководствам.

Создайте функцию PLSQL для получения вашей входной строки и возврата varchar2.

В функции PLSQL выполните asciistr () вашего ввода. PLSQL заключается в том, что он может возвращать строку длиной более 4000 и у вас есть 32K для varchar2 в PLSQL.

Эта функция преобразует символы, отличные от ASCII, в нотацию \ xxxx. Поэтому вы можете использовать регулярные выражения для их поиска и удаления. Затем верните результат.

3
ответ дан Jim Hudson 25 August 2018 в 20:11
поделиться

Сделайте это, он будет работать.

trim(replace(ntwk_slctor_key_txt, chr(0), ''))
-2
ответ дан josliber 25 August 2018 в 20:11
поделиться
  • 1
    Добро пожаловать в переполнение стека! Этот ответ появился в очереди низкого качества, по-видимому, потому, что вы не объяснили код. Если вы объясните это (в своем ответе), у вас гораздо больше шансов получить больше бонусов - и у испытуемого больше шансов узнать что-то! – The Guy with The Hat 4 August 2015 в 23:22

Я нашел ответ здесь:

http://www.squaredba.com/remove-non-ascii-characters-from-a-column-255.html

CREATE OR REPLACE FUNCTION O1DW.RECTIFY_NON_ASCII(INPUT_STR IN VARCHAR2)
RETURN VARCHAR2
IS
str VARCHAR2(2000);
act number :=0;
cnt number :=0;
askey number :=0;
OUTPUT_STR VARCHAR2(2000);
begin
str:=’^'||TO_CHAR(INPUT_STR)||’^';
cnt:=length(str);
for i in 1 .. cnt loop
askey :=0;
select ascii(substr(str,i,1)) into askey
from dual;
if askey < 32 or askey >=127 then
str :=’^'||REPLACE(str, CHR(askey),”);
end if;
end loop;
OUTPUT_STR := trim(ltrim(rtrim(trim(str),’^'),’^'));
RETURN (OUTPUT_STR);
end;
/

Затем запустите это, чтобы обновить данные

update o1dw.rate_ipselect_p_20110505
set NCANI = RECTIFY_NON_ASCII(NCANI);
2
ответ дан Matt McGurie 25 August 2018 в 20:11
поделиться

Вы можете попробовать что-то вроде следующего, чтобы найти столбец, содержащий символ не-ascii:

select * from your_table where your_col <> asciistr(your_col);
0
ответ дан Shardul Dhanorkar 25 August 2018 в 20:11
поделиться

Также работает:

select dump(a,1016), a from (
SELECT REGEXP_REPLACE (
          CONVERT (
             '3735844533120%$03  ',
             'US7ASCII',
             'WE8ISO8859P1'),
          '[^!@/\.,;:<>#$%&()_=[:alnum:][:blank:]]') a
  FROM DUAL);
22
ответ дан stealthyninja 25 August 2018 в 20:11
поделиться
  • 1
    Если длина строки близка к 4000, тогда ASCIISTR() расширит строку за пределами этого предела, и строка будет усечена до 4000 символов (потеряет лишние символы с конца). SQLFIDDLE – MT0 2 November 2015 в 02:32

Я думаю, что это сделает трюк:

SELECT REGEXP_REPLACE(COLUMN, '[^[:print:]]', '')
14
ответ дан Yuri Tkachenko 25 August 2018 в 20:11
поделиться
  • 1
    Это аккуратно и хорошо работает. Как и в adendum, вы также можете использовать REGEXP_REPLACE (Column, '[^ - ~]', ''), а не все функции Chr () и конкатенации строк, упомянутые выше. – Ciarán 2 September 2016 в 12:25
  • 2
    @Ciaran: REGEXP_REPLACE(Column,'[^ -~]','') отлично, поскольку Oracle не поддерживает '[\x80-\xFF]'. Должен быть в ответе. – mivk 7 December 2016 в 15:55
  • 3
    @ Ciarán Работает для меня спасибо. Что на самом деле означает? Является ли это стандартным регулярным выражением или чем-то уникальным для Oracle? – Learner 24 February 2017 в 07:34
  • 4
    Если вы хотите сохранить новые строки , используйте regexp_replace(column, '[^ -~|[:space:]]', '') – Learner 24 February 2017 в 07:34
  • 5
    Он задает диапазон символов ascii, то есть пробел (символ 32) - (to) tilda "~" (символ 126) asciitable.com – Ciarán 3 March 2017 в 09:09
Другие вопросы по тегам:

Похожие вопросы: