Содержит ли FreeBSD несколько вариантов основных регулярных выражений?

perl -F':|"' -lane 'if ($out && $_ eq "End") {print "$out"; $out=""};
  $out  = $F[2] if ($F[0] eq "String1");
  $out.= $F[2] if ($out && $F[0] eq "String2")' input.txt

Этот perl-скрипт использует либо :, либо "в качестве разделителя полей, чтобы избежать необходимости удалять из вывода двойные -кавычки. это означает, что нам нужно извлечь третье поле, а не второе, поскольку теперь между первым :и "есть пустое поле. Массивы Perl основаны на нуле -, так что $F[2].

Он печатает вывод только для записи ("блока" ), если есть что печатать, либо String1 сама по себе , либо String1 и String2 присутствуют -, т.е. t печатать пустые строки для не соответствующих -записей.

Вот тот же алгоритм вawk:

awk -F':|"' 'out && $0 == "End"  { print out; out="" };
  $1 == "String1" { out=$3 };
  out && $1 == "String2" { out = out$3 }' input.txt
4
05.11.2019, 13:33
1 ответ
$ echo '    aaaaa   ' | sed 's/aaaaa|bbbbb/_/g'
    aaaaa
$ echo '    aaaaa   ' | sed -E 's/aaaaa|bbbbb/_/g'
    _
$ echo '    aaaaa   ' | sed -r 's/aaaaa|bbbbb/_/g'
    _
$ echo '    aaaaa   ' | sed -E '/(aaaaa|bbbbb)/ s/ /_/g'
____aaaaa___
$ echo '    aaaaa   ' | sed -E '/aaaaa|bbbbb/ s/ /_/g'
____aaaaa___

orне является BRE (Основное регулярное выражение ). Вам нужно указать -Eдля расширенного BRE.

См. Оператор чередования/или регулярных выражений (foo|bar )в GNU или BSD Sed

ОБНОВЛЕНИЕ

Почему grep сработал?

Мы можем выбрать, какой шаблон мы хотим использовать с помощью grep

  -E, --extended-regexp     PATTERN is an extended regular expression
  -F, --fixed-strings       PATTERN is a set of newline-separated strings
  -G, --basic-regexp        PATTERN is a basic regular expression
  -P, --perl-regexp         PATTERN is a Perl regular expression
  -e, --regexp=PATTERN      use PATTERN as a regular expression

Используя эти переключатели, мы видим, что grepдействительно по умолчанию BRE и что выражение OP не работает с ERE:

$ echo '    aaaaa   ' | grep '\(aaaaa\|bbbbb\)'
    aaaaa
$ echo '    aaaaa   ' | egrep '\(aaaaa\|bbbbb\)'
$ echo '    aaaaa   ' | grep -E '\(aaaaa\|bbbbb\)'
$ echo '    aaaaa   ' | grep -G '\(aaaaa\|bbbbb\)'
    aaaaa
$ echo '    aaaaa   ' | grep -G 'aaaaa\|bbbbb'
    aaaaa
$ echo '    aaaaa   ' | grep -G 'aaaaa|bbbbb'
$ echo '    aaaaa   ' | grep -E 'aaaaa|bbbbb'
    aaaaa
$ echo '    aaaaa   ' | grep -E 'aaaaa\|bbbbb'
$ echo '    aaaaa   ' | grep -G 'bbbbb\|aaaaa'
    aaaaa
$ echo '    aaaaa   ' | grep -E 'bbbbb\|aaaaa'
$ echo '    aaaaa   ' | grep -G 'bbbbb|aaaaa'
$ echo '    aaaaa   ' | grep -E 'bbbbb|aaaaa'
    aaaaa

Оба grep и sed ссылка re _формат (7 ), в котором четко указано:

Obsolete ("basic") regular expressions differ in several respects. `|' is an ordinary character and there is no equivalent for its functionality.

Но кажется, что если мы «выходим из канала», то действительно получаем функциональность. У этого точно есть запах. Кроме того, кажется, что на этом примерном поле недавно произошел сбой -см. регулярное выражение (3 ):Добавьте тест, чтобы охватить недавнюю регрессию BRE .

И, похоже, ведется работа по замене регулярного выражения в libc.

Как Чарльз Даффи комментирует ниже

because some tools implement nonstandard extensions wherein you can use a backslash to get otherwise-ERE-only behavior in a BRE context

Я привык к очень хорошей документации по FreeBSD. Это означает, что я не уверен, задумано ли это, но не задокументировано -или поломка.

4
27.01.2020, 20:47

Теги

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