Извлеките строку между n-м шаблоном1 и m-м шаблоном2 - sed / awk - PullRequest
1 голос
/ 05 августа 2020

В приведенных ниже примерах, как можно вернуть строку между n-м шаблоном1 и m-м шаблоном2, где шаблон1 и шаблон2 могут встречаться в строке более одного раза каждый?

Лучший пример:

zz this is string xx zz another string xx third string zz xx and a tail xx

Как бы вы вернулись между вторым zz и третьим xx?

т.е.

another string xx third string zz

Изменить: Для всех, кто ищет это, «Группы захвата» и «Прямые / обратные ссылки» в регулярных выражениях кажутся терминологией для обозначения того, что требуется для этой задачи .. Здесь полезная информация .

РЕДАКТИРОВАТЬ ВЫШЕ

Извините первых помощников. Ваши ответы были хорошими, мой пример был выбран неудачно.

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

Плохой исходный вопрос и пример:

echo '1a 2b 3c 4d 5e 6f 7g 8h 9i 0j'

Бонусные баллы, если вы можете придумать решение как без конечных пробелов. Я знаю, что начальные / конечные пробелы можно удалить, снова подключив к sed, но мне любопытно, есть ли более аккуратное решение. Результат, который я ожидал (исключая одинарные кавычки):

'3c 4d 5e 6f' или ' 3c 4d 5e 6f '

  • Я использую sed / awk, так что, надеюсь, вместо того, чтобы просто сопоставить одиночный символ (пробел) it может быть расширен для соответствия n-му вхождению шаблона 1 и m-му вхождению шаблона 2 в будущем.

Я пробовал несколько вариантов. Я считаю, что это ближайший к исправлению с помощью sed:

echo '1 2 3 4 5 6 7 8 9 0' | sed -n 's/.*[ ]{2}.*[ ]{4}.*/\1/p'

Но он возвращает ошибку:

sed -e expression #1, char 28: invalid reference \1 on `s' command's RHS

Ответы [ 3 ]

3 голосов
/ 05 августа 2020

Использование любого awk в любой оболочке в каждом поле UNIX:

$ cat tst.awk
BEGIN {
    n = 2
    m = 3
}
{
    $0 = encode($0)
    beg = match($0,"([^<]*<){"n"}") + RLENGTH
    end = match($0,"([^>]*>){"m-1"}[^>]+") + RLENGTH
    print decode(substr($0,beg,end-beg))
}

function encode(str) {
    gsub(/@/,"@A",str); gsub(/</,"@B",str); gsub(/>/,"@C",str)
    gsub(/zz/,"<",str); gsub(/xx/,">",str)
    return str
}

function decode(str) {
    gsub(/>/,"xx",str); gsub(/</,"zz",str)
    gsub(/@C/,">",str); gsub(/@B/,"<",str); gsub(/@A/,"@",str)
    return str
}

.

$ awk -f tst.awk file
 another string xx third string zz

Функции encode() и decode() - это как повернуть строки вас интересуют отдельные символы, которые не могут существовать где-либо во входных данных, поэтому вы можете отрицать их в выражении в скобках, используемом в вызовах match().

3 голосов
/ 05 августа 2020

С perl

$ s='zz this is string xx zz another string xx third string zz xx and a tail xx'

$ echo "$s" | perl -pe 's/((.*?xx){3}).*/$1/'
zz this is string xx zz another string xx third string zz xx

$ echo "$s" | perl -pe 's/((.*?xx){3}).*/$1=~s#(.*?zz){2}\s*|\s*xx$##gr/e'
another string xx third string zz

Первая команда s/((.*?xx){3}).*/$1/ показывает, как получить до третьего вхождения xx, где .*? - не жадное сопоставление для минимального потребления.

Флаг e разрешает код Perl в разделе замены, поэтому вы можете изменить эту строку, чтобы удалить до второго вхождения zz и последнего xx с $1=~s#(.*?zz){2}\s*|\s*xx$##gr

2 голосов
/ 07 августа 2020

С обычным GNU sed:

pat1='zz'
n=2
pat2='xx'
m=3

echo 'zz this is string xx zz another string xx third string zz xx and a tail xx' |
sed "s/$pat1/\n/$n; s/$pat2/\n/$m; s/[^\n]*\n//; s/\n.*//"

Выводит

 another string xx third string zz    

s/$pat1/\n/$n заменяет $n th $pat1 символом новой строки.
s/$pat2/\n/$m заменяет $m th $pat2 символом новой строки.
s/[^\n]*\n// удаляет часть между начало строки и первый символ новой строки (включительно).
s/\n.*// удаляет часть между символом новой строки (включительно) и концом строки.

Примечание : sed команду можно немного упростить как sed -E "s/$pat1/\n/$n; s/$pat2/\n/$m; s/.*\n(.*)\n.*/\1/"

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