Сед редкий разделитель (кроме & | /? ...) - PullRequest
12 голосов
/ 30 января 2011

Я должен применить команду Unix sed к строке ( может содержать #,!, /,?, &, @ И все другие символы ), которая может содержать все типы символов (&, |,!, /,? ...)

Это сложный разделитель (с двумя символами?), Который позволяет обойти ошибку:

sed: -e expression #1, char 22: unknown option to `s'

Заранее спасибо

Ответы [ 8 ]

13 голосов
/ 30 января 2011

Символы во входном файле не имеют значения - sed разбирает их нормально.Однако может возникнуть проблема, если в вашем шаблоне есть большинство общих символов или если ваш шаблон может быть неизвестен заранее.

По крайней мере, в GNU sed, вы можете использовать непечатаемый символ, который крайне маловероятен в вашем шаблоне в качестве разделителя.Например, если ваша оболочка Bash :

$ echo '|||' | sed s$'\001''|'$'\001''/'$'\001''g'

В этом примере Bash заменяет $'\001' на символ, который имеет восьмеричное значение 001- в ASCII это символ SOH (начало заголовка).

Поскольку такие символы являются контрольными / непечатными символами, сомнительно, что они будут существовать в шаблоне.Если, конечно, вы не делаете что-то странное, например, модифицируете двоичные файлы - или файлы Unicode без правильных настроек локали.

2 голосов
/ 09 мая 2014

Еще один способ сделать это - использовать подстановку параметров оболочки.

${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.

1 голос
/ 26 декабря 2016

Выход из встроенного разделителя для синтаксического анализа 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.

1 голос
/ 30 января 2011

С помощью Джима Льюиса я наконец-то провел тест перед использованием sed:

if [ `echo $1 | grep '|'` ]; then
    grep ".*$1.*:" $DB_FILE  | sed "s@^.*$1*.*\(:\)@@ "
else
    grep ".*$1.*:" $DB_FILE  | sed "s|^.*$1*.*\(:\)|| "
fi

Спасибо за помощь

1 голос
/ 30 января 2011

Вам нужен вложенный разделитель, который предлагает Perl.Это позволяет использовать такие вещи, как сопоставление, подстановка и транслитерация, не беспокоясь о том, что разделитель включен в ваше содержимое.Поскольку perl является надмножеством sed, вы можете использовать его для любых целей, для которых вы используете sed.

Учтите это:

$ perl -nle 'print if /something/' inputs

Теперь, если ваш something содержитСлэш, у тебя проблема.Способ исправить это - заменить разделитель, желательно на скобки.Так, например, вы можете иметь все, что вам нравится, в переменной оболочки $ WHATEVER (при условии, что бэкеты уравновешены), которая интерполируется оболочкой до того, как здесь даже вызывается Perl:

 $ perl -nle "print if m($WHATEVER)" /usr/share/dict/words

Это работает даже есливы правильно вложили парены в $ WHATEVER.Четыре правильные пары скобок в Perl: < >, ( ), [ ] и { }.Они допускают произвольное содержимое, которое включает разделитель, если этот разделитель сбалансирован.

Если он не сбалансирован, то вообще не используйте разделитель.Если шаблон находится в переменной Perl, вам не нужно использовать оператор соответствия, если вы используете оператор =~, поэтому:

$whatever = "some arbitrary string ( / # [ etc";
if ($line =~ $whatever) { ... }
1 голос
/ 30 января 2011

Нет такой опции для разделителей многосимвольных выражений в sed, но я сомневаюсь, что вам это нужно.Символ разделителя не должен встречаться в шаблоне , но если он появляется в обрабатываемой строке, это не проблема.И если вы не делаете что-то очень странное, всегда будет какой-то символ, который не появится в вашем шаблоне поиска, который может служить разделителем.

0 голосов
/ 21 ноября 2018

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

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

Если вы находитесь в среде bash, вы можете использовать замену bash для выхода из разделителя sed, например:

safe_replace () {
    sed "s/${1//\//\\\/}/${2//\//\\\/}/g"
}

Это довольно очевидно, за исключением странной части.Объяснение этому:

${1//\//\\\/}
${            - bash expansion starts
  1           - first positional argument - the pattern
   //         - bash pattern substitution pattern separator "replace-all" variant
     \/       - literal slash
       /      - bash pattern substitution replacement separator
        \\    - literal backslash
          \/  - literal slash
            } - bash expansion ends

пример использования:

$ input="ka/pus/ta"
$ pattern="/pus/"
$ replacement="/re/"
$ safe_replace "$pattern" "$replacement" <<< "$input"
ka/re/ta
0 голосов
/ 17 января 2014

Ничего себе.Я совершенно не знал, что вы можете использовать любой символ в качестве разделителя.По крайней мере, половину времени я использую sed и BRE, используя его пути, фрагменты кода, ненужные символы и тому подобное.Я получаю кучу ужасно нечитаемых побегов, которые я даже не уверен, что не умрет от какой-то комбинации, о которой я не думал.Но если вы можете исключить только некоторый класс символов (или даже один символ)

echo '#01Y $#1+!' | sed -e 'sa$#1+ashita' -e 'su#01YuHolyug'

> > > Holy shit! Это , так что намного проще.

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