Я пытаюсь найти текст между двумя шаблонами, и это работает. Но иногда у меня бывает больше одного случая, и мне нужно было бы получить все и использовать тот, который я хочу.
Пример команды:
awk '/>23958742<\/PMID>/,/<\/PubmedArticle>/' file.xml
Я хотел бы получить все результаты и увидеть каждый из них отдельно. Как я мог получить N-й матч команды?
Я чувствую, что вы здесь задаете два разных вопроса, поэтому я просто отвечу на оба.
Здесь происходит что-то странное, потому что команда
awk '/>23958742<\/PMID>/,/<\/PubmedArticle>/' <file.xml
уже должна вывести все совпадения, а не только первое. Хотя есть альтернатива (короткая и читаемая версия):
awk '/>23958742<\/PMID>/{f=1}f==1;/<\/PubmedArticle>/{f=0}' <file.xml
awk '/>23958742<\/PMID>/ {f=1}; f==1 {print}; /<\/PubmedArticle>/ {f=0}' <file.xml
awk '/>23958742<\/PMID>/{i++}i==2&&k==1;/<\/PubmedArticle>/{k++}' <file.xml
awk '/>23958742<\/PMID>/ {i++}; i==2 && k==1 {print}; /<\/PubmedArticle>/ {k++}' <file.xml
Это будет просто подсчитывать вхождения ваших строк, сохраняя значения в i
и k
и печатать каждую строку, пока выполняются условия i==2&&k==1
. Я выбрал второй блок в качестве примера, для третьего это будет i==3&&k==2
. k
отсчет идет после условий, потому что я понял, что вы хотели, чтобы обе совпавшие строки также были напечатаны. Если вам нужно только то, что находится между и , строки поиска переворачивают все вокруг:
awk '/<\/PubmedArticle>/{k++}i==2&&k==1;/>23958742<\/PMID>/{i++}' <file.xml
awk '/<\/PubmedArticle>/ {k++}; i==2 && k==1 {print}; />23958742<\/PMID>/ {i++}' <file.xml
Я всегда позволяю оболочке открывать входной файл и назначать его в стандартный поток программы (<file.xml
) потому что это имеет ряд преимуществ, см. здесь . Я нашел помощь здесь и здесь .
Общее решение, предложенное тердоном , таково:
awk -vn=2 '/>23958742<\/PMID>/{i++;k=1}i==n&&k==1;/<\/PubmedArticle>/{k=0}' <file.xml
awk -vn=2 '/>23958742<\/PMID>/ {i++;k=1}; i==n && k==1 {print}; /<\/PubmedArticle>/ {k=0}' <file.xml
Для этого вам просто нужно установить n
с опцией -v
, например, -vn=2
для второго матча.