Это сделает задание
sed '/^ONE/,/TWO/{/^ONE/!{/TWO/!d}}' file
/^ONE/,/TWO/
Посмотрите на первую строку, запускающуюся с ONE
до TWO
{/^ONE/!
сделайте следующее, если моя строка не запускается с ONE
{/TWO/!d}}
сделайте следующее, если моя строка не запускается с TWO
и delete
К summerize вышеупомянутому:
Найдите все, что запускается с ONE
до TWO
. Другая проверка, работал, что означает, найдите все, что не соответствует 'ОДИНand
ДВА' и удаляют остальных.
через 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
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
Так или иначе, это работает по:
y|]|\n|
- Сначала он переводит все вхождения ]
на строку для \n
ewline. s|\n>/string>|]|
- Далее она заменяет первую возникающую \n
эвлайну, за которой сразу же следует ваш правосторонний разделитель на ]
(что делает ее единственно возможной ]
на линии на тот момент). y|[]\n|\n[]|
- Если последняя замена прошла успешно, то одна ]
переводится на [
, а все \n
ewlines переводятся обратно на ]
и все [
одновременно переводятся на \n
ewlines - три типа символов смещены, По сути. s|string>!\nTEST\n\(.*\[\)|[\1|
- Если левый конец разделителя найден перед [
на тот момент, то должны быть найдены оба конца первого появления текста . Это совпадение заменяется на [
. y|\n[|[\n|
- И так в последнем переводе, если в строке вообще есть [
, то они станут новыми строками и все новые строки станут [
. В этот момент всё, вплоть до первой возникающей новой строки (или всей строки, если её вообще нет) имеет значение D
eleted. Если что-то остаётся, оно отправляется в верхнюю часть скрипта. Если предыдущая итерация привела к двум \n
овечьим линиям в шаблоне - оба конца вашего разделенного текста , то это P
отрисовывается до первой возникающей \n
овечьей линии. В противном случае уже проверенное пространство шаблона будет очищено, и цикл продолжится.
И так в приведенном выше примере печатается:
][]Extract[ ]this[ ]string[][
... и каждый из них будет напечатан на отдельной линии столько же одинаково разделенных строк, сколько может быть полностью разделенных на левую и правую линию, или вообще ничего.
sed -e 's/string>!\[TEST\[\(.*\)]>\/string>/\1/' file
или
sed -e 's|string>!\[TEST\[\(.*\)]>/string>|\1|' file
Вывод:
Extract this string
Вам нужно указать строке не только, что именно совпадает, но и что сохранить:
sed -ne 's@string>!\[TEST\[\([^]]*\)\]>/string>@\1@gp'
Команда s
в sed
принимает два аргумента: регулярное выражение и строку-замену. Обычно разделитель /
используется для разделения этих двух аргументов, но вы можете использовать любой символ, в данном случае @
. В регулярных выражениях есть специальные символы, такие как [
, ]
. Они должны быть процитированы с помощью \
, если вам нужен реальный символ, например, string>!\[
. \([^]]*\)
перехватывает все, что заключено в квадратные скобки. А \1
заменяет строку who на то, что соответствовало регулярному выражению. В конце находится @gp
, который говорит send to match несколько раз на строке (g
) и выводит замененную строку (после того, как мы скажем sed
не выводить строки с опцией -n
).