Как правильно найти и заменить многострочный текст с помощью sed или awk? - PullRequest
0 голосов
/ 07 января 2020

При попытке заменить следующий текст я получаю сообщение об ошибке:

sed -i "s/  type pulse
  fallback "sysdefault"
  hint {
    show on
    description "Default ALSA Output (currently PulseAudio Sound Server)"
  }/  type plug
      slave.pcm hw/g" .asoundrc

совпадений не найдено: (в настоящее время звуковой сервер PulseAudio) \ n} / type plug \ n slave.pcm hw / g

Я уже пытался избежать "использования \ или обмена ими", но ошибка:

sed: -e выражение # 1, символ 14 : unterminated `s 'command

Связана ли проблема с пустым пробелом / новыми строками? Какой самый простой способ сделать это, используя sed, awk или perl? Большое спасибо !

Ответы [ 3 ]

1 голос
/ 07 января 2020

Команды в sed разделены переводом строки. Чтобы сопоставить многострочные строки, вы можете прочитать несколько строк в шаблонном пространстве с помощью команды N, а затем сопоставить их с регулярным выражением \n для сопоставления новой строки. Если совпадение не найдено, вы должны перемешать с пробелом: удерживать пробел, печатать все до новой строки, переключать пробел с пробелом, удалять из паттерна все до первой новой строки, читать следующую строку, повторять.

Это было бы что-то вроде:

sed '
  : restart
  N;N;N;N;N; # read six lines, we need that many
  : loop
      # match six lines
      /  type pulse\n  fallback "sysdefault"\n  hint {\n    show on\n    description "Default ALSA Output (currently PulseAudio Sound Server)"\n  }/{
           # replace them
           s//    type plug\n      slave.pcm hw/
           # print and start over
           n ; b restart
       }
       # hold, print leading line, change, remove leading line
       h ; s/\n.*// ; p ; x ; s/[^\n]*\n//
       # append next line and loop
       N
  b loop
'

Поскольку написание таких скриптов сложно (для большинства людей;), некоторые просто используют GNU sed -z option:

sed -z 's/  type pulse\n  fallback "sysdefault"\n  hint {\n    show on\n    description "Default ALSA Output (currently PulseAudio Sound Server)"\n  }/  type plug\n      slave.pcm hw/g'

Заметьте, я думаю, что использование \n в строке замены внутри команды s в любом случае является расширением GNU.

1 голос
/ 07 января 2020

Использование в многострочном режиме:

perl -i -0 -pe '
    s/type pulse.*PulseAudio Sound Server\)/  type plug\n    slave.pcm hw/s
' file

Вывод

type plug
slave.pcm hw

Примечание

Чего вы действительно пытаетесь достичь ? Может быть, есть лучший способ.

0 голосов
/ 08 января 2020

Как отмечают другие, sed обрабатывает файл построчно и не может обрабатывать несколько строк в качестве поведения по умолчанию. Возможный обходной путь - отбросить все строки в пространстве шаблона с помощью команды N на первом этапе и выполнить подстановку (и) на следующем этапе. Тогда как насчет:

sed '
:l
N
$!b l
s/ *type pulse\n *fallback "sysdefault"\n *hint {\n *show on\n *description "Default ALSA Output (currently PulseAudio Sound Server)"\n *}/  type plug\'$'\n''  slave.pcm hw/g' .asoundrc

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

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