Как я могу напечатать несколько шаблонов на отдельных строках - PullRequest
0 голосов
/ 17 апреля 2019

У меня есть файл, который я хотел бы обработать с помощью bash.Может быть с awk, sed или grep или подобным.Файл имеет несколько вхождений в одной строке.Я хотел бы извлечь все между этими двумя вхождениями и распечатать вывод каждого в отдельной строке.

Я уже пробовал использовать это:

cat file.txt | grep -o 'pattern1.*pattern2'

Но это будет печатать все, что соответствует pattern1до самого последнего совпадающего шаблона2.

$ cat file.txt
pattern1 this is the first content pattern2 this is some other stuff pattern1 this is the second content pattern2 this is the end of the file.

Я бы хотел получить:

pattern1 this is the first content pattern2
pattern1 this is the second content pattern2

Ответы [ 3 ]

1 голос
/ 18 апреля 2019

Это может работать для вас (GNU sed):

sed -n '/pattern1.*pattern2/{s/pattern1/\n&/;s/.*\n//;s/pattern2/&\n/;P;D}' file

Установите опцию -n для явной печати. ​​

Только те строки процесса, которые содержат pattern1, за которыми следует pattern2.

Добавить новую строку к pattern1.

Удалить до и включая введенную новую строку.

Добавить новую строку после pattern2.

Выведите первую строку в шаблонном пространстве, удалите ее и повторите.

0 голосов
/ 17 апреля 2019

В случае, если у вас нет доступа к инструментам, которые поддерживают обходные пути, этот подход, хотя и длительный, будет надежно работать с использованием стандартных инструментов на любой машине UNIX:

awk '{
    gsub(/@/,"@A"); gsub(/{/,"@B"); gsub(/}/,"@C"); gsub(/pattern1/,"{"); gsub(/pattern2/,"}")
    out = ""
    while( match($0,/{[^{}]*}/) ) {
        out = (out=="" ? "" : out ORS) substr($0,RSTART,RLENGTH)
        $0 = substr($0,RSTART+RLENGTH)
    }
    $0 = out
    gsub(/}/,"pattern2"); gsub(/{/,"pattern1"); gsub(/}/,"@C"); gsub(/{/,"@B"); gsub(/@A/,"@")
} 1' file

Вышеописанное работает путем создания символов, которые не могут существовать во входных данных (сначала изменяя эти символы { и } на некоторые другие строки @B и @C), чтобы они могли использовать эти символы в отрицательный символьный класс, чтобы найти целевые строки, а затем он возвращает все измененные символы в их исходные значения. Вот некоторые рисунки, чтобы сделать более очевидным, что происходит на каждом шаге:

awk '{
    print "1): " $0 ORS
    gsub(/@/,"@A"); gsub(/{/,"@B"); gsub(/}/,"@C"); gsub(/pattern1/,"{"); gsub(/pattern2/,"}")
    print "2): " $0 ORS
    out = ""
    while( match($0,/{[^{}]*}/) ) {
        out = (out=="" ? "" : out ORS) substr($0,RSTART,RLENGTH)
        $0 = substr($0,RSTART+RLENGTH)
    }
    $0 = out
    print "3): " $0 ORS
    gsub(/}/,"pattern2"); gsub(/{/,"pattern1"); gsub(/}/,"@C"); gsub(/{/,"@B"); gsub(/@A/,"@")
    print "4): " $0 ORS
} 1' file
1): pattern1 this is the first content pattern2 this is some other stuff pattern1 this is the second content pattern2 this is the end of the file.

2): { this is the first content } this is some other stuff { this is the second content } this is the end of the file.

3): { this is the first content }
{ this is the second content }

4): pattern1 this is the first content pattern2
pattern1 this is the second content pattern2

pattern1 this is the first content pattern2
pattern1 this is the second content pattern2
0 голосов
/ 17 апреля 2019

попробуйте GNU SED:

 sed -E 's/(pattern2).*(pattern1)(.*\1).*/\1\n\2\3/' file.txt
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...