Как извлечь текст с помощью sed

Это сделает задание

sed '/^ONE/,/TWO/{/^ONE/!{/TWO/!d}}' file

/^ONE/,/TWO/ Посмотрите на первую строку, запускающуюся с ONE до TWO

{/^ONE/! сделайте следующее, если моя строка не запускается с ONE

{/TWO/!d}} сделайте следующее, если моя строка не запускается с TWO и delete

К summerize вышеупомянутому:

Найдите все, что запускается с ONE до TWO. Другая проверка, работал, что означает, найдите все, что не соответствует 'ОДИНandДВА' и удаляют остальных.

3
28.01.2017, 01:00
5 ответов

через GNU GREP ,

$ echo 'string>![TEST[Extract this string]>/string> foo bar string>![TEST[Extract this string]>/string>' | grep -oP 'string>!\[TEST\[\K.*?(?=]>/string>)'
Extract this string
Extract this string
1
27.01.2020, 21:07
sed '/\n/P;//D;y|]|\n|
    s|\n>/string>|]|
    y|[]\n|\n[]|
    s|string>!\nTEST\n\(.*\[\)|[\1|
    y|\n[|[\n|;D' <<\IN
    string>![TEST[][]Extract[ ]this[ ]string[][]>/string>
IN

Может быть, здесь можно указать, что квадратные скобки являются приемлемыми разделителями, но, если это так, то странно, что конечные разделители в этом случае будут настолько сложными. И в любом случае, так как в вопросе говорится только о том, что вам нужно получить text из промежутка между string>![TEST[ и ]>/string> и вот что это пытается сделать - хотя и не получается, если text должен выходить за границы новой строки. I

Так или иначе, это работает по:

  1. y|]|\n| - Сначала он переводит все вхождения ] на строку для \newline.
  2. s|\n>/string>|]| - Далее она заменяет первую возникающую \nэвлайну, за которой сразу же следует ваш правосторонний разделитель на ] (что делает ее единственно возможной ] на линии на тот момент).
  3. y|[]\n|\n[]| - Если последняя замена прошла успешно, то одна ] переводится на [, а все \newlines переводятся обратно на ] и все [ одновременно переводятся на \newlines - три типа символов смещены, По сути.
  4. s|string>!\nTEST\n\(.*\[\)|[\1| - Если левый конец разделителя найден перед [ на тот момент, то должны быть найдены оба конца первого появления текста . Это совпадение заменяется на [.
  5. y|\n[|[\n| - И так в последнем переводе, если в строке вообще есть [, то они станут новыми строками и все новые строки станут [.

В этот момент всё, вплоть до первой возникающей новой строки (или всей строки, если её вообще нет) имеет значение Deleted. Если что-то остаётся, оно отправляется в верхнюю часть скрипта. Если предыдущая итерация привела к двум \nовечьим линиям в шаблоне - оба конца вашего разделенного текста , то это Pотрисовывается до первой возникающей \nовечьей линии. В противном случае уже проверенное пространство шаблона будет очищено, и цикл продолжится.

И так в приведенном выше примере печатается:

][]Extract[ ]this[ ]string[][

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

2
27.01.2020, 21:07

Простой подход с awk:

awk -F'[][]' '{print $3}' file
4
27.01.2020, 21:07
sed -e 's/string>!\[TEST\[\(.*\)]>\/string>/\1/' file

или

sed -e 's|string>!\[TEST\[\(.*\)]>/string>|\1|' file

Вывод:

Extract this string
6
27.01.2020, 21:07

Вам нужно указать строке не только, что именно совпадает, но и что сохранить:

sed -ne 's@string>!\[TEST\[\([^]]*\)\]>/string>@\1@gp'

Команда s в sed принимает два аргумента: регулярное выражение и строку-замену. Обычно разделитель / используется для разделения этих двух аргументов, но вы можете использовать любой символ, в данном случае @. В регулярных выражениях есть специальные символы, такие как [, ]. Они должны быть процитированы с помощью \, если вам нужен реальный символ, например, string>!\[. \([^]]*\) перехватывает все, что заключено в квадратные скобки. А \1 заменяет строку who на то, что соответствовало регулярному выражению. В конце находится @gp, который говорит send to match несколько раз на строке (g) и выводит замененную строку (после того, как мы скажем sed не выводить строки с опцией -n).

5
27.01.2020, 21:07

Теги

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