Как удалить строки до и после соответствия шаблону

У меня есть файл, как показано ниже. Я хочу найти шаблон ABC_DATA как переменную, и после совпадения я хочу удалить из первой предыдущей строки "multipath" строку, содержащую символ "}". "}" может быть после или в одной строке с ABC_DATA.

ОБРАЗЕЦ ВЫХОД

multipaths {
multipath {
wwid 360000970000267600432533030353944
alias ABC_DATA_11
}
multipath {
wwid 360000970000267600432533030353945
alias DEF_DATA_11
}
multipath {
wwid 360000970000267600432533030353946
alias ABC_DATA_12 }

multipath {
wwid 360000970000267600432533030353943
alias DEF_DATA_10
}
}

ОЖИДАЕМЫЙ ВЫХОД

multipaths {
multipath {
wwid 360000970000267600432533030353945
alias DEF_DATA_11
}
multipath {
wwid 360000970000267600432533030353943
alias DEF_DATA_10
}
}

4 ответа

Решение
$ awk -v RS='multipath\\s*{[^}]*ABC_DATA[^}]*}\\s*(\n|$)' -v ORS= '1' file
multipaths {
multipath {
wwid 360000970000267600432533030353945
alias DEF_DATA_11
}
multipath {
wwid 360000970000267600432533030353943
alias DEF_DATA_10
}
}

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

sed '
   /^multipath {/ {
     :l
     /alias ABC_DATA/ {
       :f
       /}/ d
       N
       b f
     }
     /}/ b
     N
     b l
  }' input

или одной строкой:

sed '/^multipath {/{:l; /alias ABC_DATA/{:f /}/d;N;bf};/}/b;N;bl};' input

Учитывая ваш пример, вы можете использовать это perl:

$ perl -0777 -lpe 's/\bmultipath\h+\{[^{}]*ABC_DATA[^{}]*}\s*//g' file
multipaths {
multipath {
wwid 360000970000267600432533030353945
alias DEF_DATA_11
}
multipath {
wwid 360000970000267600432533030353943
alias DEF_DATA_10
}
}

ed(1) тоже работает, если у вас есть строки глобального поиска, отличные от строк начала и конца области, которую вы хотите удалить:

      echo $'g/ABC_DATA/?multipath?,/[\s\S]*}/s/.*//g\n ,n\n w\n q' | ed -s file
#or
echo $'g/ABC_DATA/?multipath?,/[\s\S]*}/d\n ,n\n w\n q' | ed -s file
  • echoкоманда предоставляет команды ed,\nэто просто новые строки
  • того же можно добиться с помощью файлов heredocs или ed script, но это не работает для oneliners

что там на самом деле происходит:

  • поиск ABC_DATA
  • оттуда получите стартовую строку, выполнив поискmultipathвверх
  • получите конечную строку, выполнив поиск любого символа вниз ([\s\S]*) и заканчивая
  • и либо «отправить» его черезsили удалить черезd
  • ,nпредназначен только для печати всего вывода в оболочку и может быть опущен
  • wсохраняет иqвыходы - используйтеQвместо того и другого, если вы все еще экспериментируете и не хотите немедленно сохранять изменения обратно в файл.

однако для этого примера это не удастся из-за строки, содержащейalias ABC_DATA_12 }Как обаABC_DATAи}находятся на одном уровне - я все еще вижу преимущества использования ed(1) и поэтому хотел поделиться этим подходом.

Другие вопросы по тегам