Sed редкий-разделитель (кроме & |/?...)
Я должен применить команду Unix sed к строке (может содержать #,!,/,?, &, @и все остальные символы), которые может содержать все типы символов (&, |,!,/,?...)
Является ли это сложным разделителем (с двумя символами?), который позволяет исключить ошибку:
sed: -e expression #1, char 22: unknown option to `s'
Заранее спасибо
Ответы
Ответ 1
В sed нет такой опции для мультисимвольных разделителей выражений, но я сомневаюсь
вам это нужно. Символ разделителя не должен встречаться в шаблоне, но если он появляется в обрабатываемой строке, это не проблема. И если вы не делаете что-то чрезвычайно странное, всегда будет какой-то символ, который не отображается в вашем шаблоне поиска, который может служить разделителем.
Ответ 2
Символы входного файла не имеют значения - sed
отлично разбирает их. Однако может возникнуть проблема, если у вас есть большинство общих символов в вашем шаблоне - или если ваш шаблон не может быть заранее известен.
По крайней мере на GNU sed вы можете использовать непечатаемый символ, который очень маловероятен для существования в вашем шаблоне в качестве разделителя. Например, если ваша оболочка Bash:
$ echo '|||' | sed s$'\001''|'$'\001''/'$'\001''g'
В этом примере Bash заменяет $'\001'
символом с восьмеричным значением 001
- в ASCII это SOH символ (начало заголовка).
Поскольку такие символы являются управляющими/непечатаемыми символами, сомнительно, что они будут существовать в шаблоне. Если, то есть, вы делаете что-то странное, как изменение двоичных файлов, или файлы Unicode без правильных настроек локали.
Ответ 3
Другой способ сделать это - использовать замену параметров Shell.
${parameter/pattern/replace} # substitute replace for pattern once
или
${parameter//pattern/replace} # substitute replace for pattern everywhere
Вот довольно сложный пример, сложный с sed:
$ parameter="Common sed delimiters: [sed-del]"
$ pattern="\[sed-del\]"
$ replace="[/_%:\\@]"
$ echo "${parameter//$pattern/replace}"
результат:
Common sed delimiters: [/_%:\@]
Однако: Это работает только с параметрами bash, а не с файлами, где sed
excel.
Ответ 4
Вам нужен объект вложенного ограничителя, который предлагает Perl. Это позволяет использовать такие вещи, как сопоставление, подстановка и транслитерация, не беспокоясь о том, что разделитель включен в ваше содержимое. Поскольку perl является надмножеством sed, вы можете использовать его для любого использования sed.
Рассмотрим это:
$ perl -nle 'print if /something/' inputs
Теперь, если ваш something
содержит косую черту, у вас есть проблема. Способ исправить это - изменить разделитель, предпочтительно на брекетинг. Так, например, вы могли бы иметь что угодно, как в переменной оболочки WHEREVER (при условии, что баланс сбалансирован), который интерпретируется оболочкой до того, как Perl даже вызывается здесь:
$ perl -nle "print if m($WHATEVER)" /usr/share/dict/words
Это работает, даже если вы правильно ввели parens в $WHATEVER. Четыре пары брекетинга, которые правильно вложены в Perl, равны < >
, ( )
, [ ]
и { }
. Они позволяют произвольное содержимое включать разделитель, если этот разделитель сбалансирован.
Если он не сбалансирован, тогда не используйте разделитель вообще. Если шаблон находится в переменной Perl, вам не нужно использовать оператор сопоставления, если вы используете оператор =~
, поэтому:
$whatever = "some arbitrary string ( / # [ etc";
if ($line =~ $whatever) { ... }
Ответ 5
С помощью Джима Льюиса я, наконец, сделал тест перед использованием sed:
if [ `echo $1 | grep '|'` ]; then
grep ".*$1.*:" $DB_FILE | sed "[email protected]^.*$1*.*\(:\)@@ "
else
grep ".*$1.*:" $DB_FILE | sed "s|^.*$1*.*\(:\)|| "
fi
Спасибо за помощь
Ответ 6
Ого. Я полностью не знал, что вы можете использовать любого персонажа в качестве разделителя.
По крайней мере, в половине случаев я использую sed и BREs на своих путях, фрагментах кода, мусорных символах, подобных вещах. Я в конечном итоге с кучей ужасно нечитаемых побегов, которые я даже не уверен, не умрут в какой-то комбинации, о которой я не думал. Но если вы можете исключить только некоторый класс символов (или только один символ)
echo '#01Y $#1+!' | sed -e 'sa$#1+ashita' -e 'su#01YuHolyug'
> > > Holy shit!
Это намного проще.
Ответ 7
Удаление разделителя inline для BASH для синтаксического анализа является громоздким и трудным для чтения (хотя разделитель действительно нуждается в ускорении для выгоды sed, когда он впервые использовался, для выражения).
Чтобы собрать thkala ответ и user4401178 комментарий:
DELIM=$(echo -en "\001");
sed -n "\\${DELIM}${STARTING_SEARCH_TERM}${DELIM},\\${DELIM}${ENDING_SEARCH_TERM}${DELIM}p" "${FILE}"
В этом примере возвращаются все результаты, начиная с ${STARTING_SEARCH_TERM}
до ${ENDING_SEARCH_TERM}
, которые не соответствуют символу SOH
(начало заголовка) с кодом ASCII 001.