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
$ 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. Это означает, что я не уверен, задумано ли это, но не задокументировано -или поломка.