Подтвердить что ты не робот

Регулярное выражение Sed и отрицание подстроки

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

Например, я хочу взять все подстроки, которые начинаются с BEGIN_, заканчиваются на _END, а подстрока между ними не равна FOO; и заменить всю подстроку на формат "(внутренняя подстрока)". Следующее будет соответствовать:

  • BEGIN_bar_END(bar)
  • BEGIN_buz_END(buz)
  • BEGIN_ihfd8f398IHFf9f39_END(ihfd8f398IHFf9f39)

Но BEGIN_FOO_END не соответствует.

Я играл со следующим, но не могу найти правильный синтаксис:

sed -e 's/BEGIN_(^FOO)_END/($1)/g'
sed -e 's/BEGIN_([^FOO])_END/($1)/g'
sed -e 's/BEGIN_(?!FOO)_END/($1)/g'
sed -e 's/BEGIN_(!FOO)_END/($1)/g'
sed -e 's/BEGIN_(FOO)!_END/($1)/g'
sed -e 's/BEGIN_!(FOO)_END/($1)/g'
4b9b3361

Ответ 1

В Sed, IIRC нет общего оператора отрицания, поскольку компиляция регулярных выражений с отрицанием DFA занимает экспоненциальное время. Вы можете обойти это с помощью

'/BEGIN_FOO_END/b; s/BEGIN_\(.*\)_END/(\1)/g'

где /BEGIN_FOO_END/b означает: если мы найдем BEGIN_FOO_END, то ветвь (прыжок) в конец Sed script.

Ответ 3

Это может сработать для вас:

sed 'h;s/BEGIN_\(.*\)_END/(\1)/;/^(FOO)$/g' file

Это работает только в том случае, если в строке есть только одна строка.

Для нескольких строк в строке:

sed 's/BEGIN_\([^F][^_]*\|F[^O][^_]*\|FO[^O][^_]*\|FOO[^_]\+\)_END/\(\1\)/g' file

Или легче понять:

sed 's/\(BEGIN_\)FOO\(_END\)/\1\n\2/g;s/BEGIN_\([^\n_]*\)_END/(\1\)/g;s/\n/FOO/g' file

Ответ 4

Я не знаю, как это сделать, но вы всегда можете это сделать:

$ cat file
BEGIN_FOO_END
BEGIN_FrOO_END
BEGIN_rFOO_END
$ sed '/BEGIN_FOO_END/ !{s/BEGIN_\([^_]*\)_END/(\1)/}' file 
BEGIN_FOO_END
(FrOO)
(rFOO)