Должен вставить одинарные кавычки в текстовый файл для использования в качестве SQL-запроса с помощью sed

что случилось со следующим?

make -C <kernel source root directory>/tools/perf
3
18.11.2018, 19:16
3 ответа

Существует четыре способа включить единственную цитату, которую вам нужно.

Невозможно избежать ни одной строки кавычек в пределах одной цитируемой строки. Однако можно заканчивать цитируемую строку, вставьте сбежавшую одноцитату, а затем запустите новую односимурируемую строку. Таким образом, поставить одну цитату в середине «AB» , используйте: 'A' \ '' B '. Или, используя команду SED, которая вам нужна:

$ sed -r 's/,([^ ),]+)/,'\''\1'\''/g; s/,,/,'\'\'',/g' file
INSERT INTO radcheck(id, username, attribute, op, value) VALUES (,'','00:23:32:c2:a9:e8','Auth-Type',':=','Accept');

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

$ sed -r "s/,([^ ),]+)/,'\1'/g; s/,,/,'',/g" file
INSERT INTO radcheck(id, username, attribute, op, value) VALUES (,'','00:23:32:c2:a9:e8','Auth-Type',':=','Accept');

Эта проблема с двойными цитируемыми строками состоит в том, что Оболочка делает обработку на них. Здесь, однако, нет активных символов, поэтому это легко.

Третий метод состоит в том, чтобы использовать Hex Escape, поскольку PM2RING демонстрирует.

Четвертый путь, предложенный в комментариях Джонатана Лейффлера, заключается в том, чтобы разместить команды SED в отдельном файле:

$ cat script.sed 
s/,([^ ),]+)/,'\1'/g
s/,,/,'',/g
$ sed -rf script.sed file
INSERT INTO radcheck(id, username, attribute, op, value) VALUES (,'','00:23:32:c2:a9:e8','Auth-Type',':=','Accept');

Таким образом, имеет сильное преимущество SED Команды непосредственно без каких-либо помех от оболочки. Следовательно, это полностью избегает необходимости избежать активных символов оболочки и позволяет вводить команды в чисто SED синтаксис .

Как работает SED решение

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

  • S /, ([^),] +) /, '\ 1' / G

    Это ищет одно или несколько несобностей, не -COMMA и не закрытые символы, которые следуют за запятую. Эти символы размещаются внутри одиночных кавычек.

  • S / ,, /, '', / G

    Это ищет последовательные запятые и помещает две односмысленные цитаты между ними.

OSX и другие платформы BSD

, чтобы избежать дополнительных задних чехлов, вышеупомянутые выражения SED используют расширенные регулярные выражения. С GNU они вызываются как -R , но, с BSD, они называются -E . Кроме того, некоторые не GNU SED не принимают несколько команд, разделенных с запятой. Таким образом, на OSX, попробуйте:

sed -E -e "s/,([^ ),]+)/,'\1'/g" -e "s/,,/,'',/g" file

Дополнение: сопоставление MAC-адреса

из комментариев, у нас есть следующий вход;

$ cat file3
 INSERT INTO radcheck(username, attribute, op, value) VALUES (00:23:32:c2:a9:e8,'Auth-Type',':=','Accept'); 

и, мы хотим поставить однозначные цитаты вокруг MAC-адреса, который следует за открытым Parens. Для этого:

$ sed -r "s/\(([[:xdigit:]:]+)/('\1'/" file3
 INSERT INTO radcheck(username, attribute, op, value) VALUES ('00:23:32:c2:a9:e8','Auth-Type',':=','Accept'); 

в любой локали, [: XDIGIT:] будет соответствовать любой шестнадцатеричной цифре. Таким образом, ([[: xDIGIT:]:] +) будет соответствовать MAC-адресу (Hex Digit или Colon).

9
27.01.2020, 21:09

Попробуйте:

SED 'S / ,, /, \ x27 \ x27, /'

\ x27 - это код Escape Hex для

DEMO

$ echo 'INSERT INTO `radcheck`(`id`, `username`, `attribute`, `op`, `value`) VALUES (,,00:23:32:c2:a9:e8,Auth-Type,:=,Accept);' |
> sed 's/,,/,\x27\x27,/'
INSERT INTO `radcheck`(`id`, `username`, `attribute`, `op`, `value`) VALUES (,'',00:23:32:c2:a9:e8,Auth-Type,:=,Accept);
1
27.01.2020, 21:09

Когда вы работаете глобально, вы должны подумать о том, как sed читает. Лобальная замена gразделит пространство шаблонов на отдельные поля, разделенные в соответствии с вашими спецификациями, и будет работать с каждым из них. Разделители распознаются слева направо - в порядке их считывания - и sed применит каждое действие, как только это будет возможно. Вот единственное утверждение s///ubstitution, которое может делать то, что вы просите:

sed "s/\(([^)]*)[^,]*\)\{0,1\},\([^,)]*\)/\1,'\2'/g
" <<\IN
INSERT INTO radcheck(id, username, attribute, op, value) VALUES (,,00:23:32:c2:a9:e8,Auth-Type,:=,Accept);

When run, that print:

INSERT INTO radcheck(id, username, attribute, op, value) VALUES (,'','00:23:32:c2:a9:e8','Auth-Type',':=','Accept');

Here's how:

  • \(((([^)]*)[^,]*\)\{0,1\} - Самое важное - это распределение *zero+ совпадений и другого вида. Весь этот блок необязателен - sed будет счастливо сопоставлять нулевую строку на своем месте при такой возможности - и на самом деле делает это часто, иначе это вообще не сработало бы. Но так как используется \{0,1\} sed, то не будет совпадать больше , чем целая последовательность, подобная этой. И поэтому распределение важно. Внутри этого блока мы имеем:
    • ( - хотя бы один левый родитель.
    • [^)]* - ноль+ не-правых парен.
    • ) - один правый родитель
    • .
    • [^,]* - ноль+ не-комм.
  • sed будет соответствовать каждой из них по порядку - и как блок, потому что они \(сгруппированы\). Совпадение *zero+ является очень важным в глобальном масштабе - если вы используете + хотя бы одну из этих настроек, то вы резко снижаете эффективность применяемых вами правок. Для простого ввода блока выше, sed разделяет вашу строку таким образом:

  • INSERT INTO radcheck - Эта строка приходит до любого из наших совпадений и не содержит ни одного из них. Она игнорируется.

  • (id, имя пользователя, атрибут, оп, значение) VALUES ( - Эта строка составляет весь наш дополнительный блок совпадений *. Сначала sed совпадает с (), затем вся строка [^)]*, затем ) и последняя - и это важно - вся строка [^,]*, которая переносит нас за еще один случай совпадения для (). Теперь она не может совпасть - и поэтому пропустите следующую () для этой необязательной группы совпадений. sed попробует вместо этого следующую.

И пока sed применяет замены для \2 во второй последовательности (...,..), она будет по-прежнему применять замены для \1, так как она все еще совпадает с \1. Впервые я сравнил \1 как весь (...,...)...() блок, сохранил его в \1 и заменил на \1 - на себя. От начала второй последовательности до следующей происходящей ( sed заменит \1 на нулевую строку каждый раз, когда она совпадает с одной - то есть каждый раз, когда она совпадает с запятой.

Учитывая множество последовательностей, подобных этой, на строке - и учитывая, что запятые встречаются только внутри разделителей ( ), sed будет поочередно кавычки для каждой из последовательностей. Вот Ваш пример несколько раз:

INSERT INTO radcheck(id, username, attribute, op, value) VALUES (,'','00:23:32:c2:a9:e8','Auth-Type',':=','Accept');INSERT INTO radcheck(id, username, attribute, op, value) VALUES (,'','00:23:32:c2:a9:e8','Auth-Type',':=','Accept');INSERT INTO radcheck(id, username, attribute, op, value) VALUES (,'','00:23:32:c2:a9:e8','Auth-Type',':=','Accept');
  • ,\([^,)]*\) - обратите внимание, что единственным дополнительным совпадением не для всего регекса является запятая ,. Другой блок встречается перед ним в выражении и во входе, поэтому sed позволяет его применить - но запятая имеет приоритет, когда все остальное равно, и это единственная причина, по которой sed не вставляет '' везде, так как все нуль-строки между каждым байтом на двух других блоках совпадают не с нуль-строками при применении - sed разделителей на ней.
  • sed будет продолжать совпадать с \2 - и сохранит к нему - каждую последовательность символов, которые не являются ), а не ,. Каждая запятая будет заменена на встречу с , '\2'. Так будет продолжаться до тех пор, пока не встретится с (, после чего можно будет заполнить \1, и так будет сделано.
2
27.01.2020, 21:09

Теги

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