Для тех из вас, кто, возможно, раньше не слышал об AWK, это язык обработки текста и сценариев, который устанавливается вместе с UNIX. Насколько мне известно, большинство, если не все, UNIX и UNIX-подобные операционные системы, которые существуют или когда-либо будут существовать, поставляются или будут поставляться с этой полезной маленькой утилитой. Итак, если вы пользователь или разработчик Unix/Linux, с этим определенно стоит познакомиться.
Если вам интересно, название AWK — это просто инициалы трех его создателей: Ахо, Вайнбергера и Кернигана — да, этого Кернигана.
Итак, вот несколько вариантов использования сопоставления с образцом, для которых AWK идеально подходит.
Предположим, вам нужно найти шаблон в текстовом файле, распечатать строку, содержащую его, а также распечатать n-ю строку после этого.
Вот один из способов.
Прежде всего, вот входной текстовый файл, который я ищу. Мы назовем его x.txt
AAAA BBBB CCCC DDDD Line 2 Line 3 Line 4 Line 5 Line 6 Line 7 Line 8
Допустим, я хочу найти строку, содержащую текст BBBB, распечатать ее, а также распечатать 3-ю строку после этой строки, т.е. Line 4.
Итак, мы хотим, чтобы это было результатом:
AAAA BBBB CCCC DDDD Line 4
Следующая команда AWK сделает это.
awk "/BBBB/{i=1;print}!i{next}{if(i++==4){print}}" x.txt
Вы можете немного расширить это, изменив строку if(i++==4). Допустим, вам нужна целевая строка плюс строки 3, 4 и 5 после нее.
e.g AAAA BBBB CCCC DDDD Line 3 Line 4 Line 5
Это сделает это.
awk "/BBBB/{i=1;print}!i{next}{if(i++>=3 && i <= 6){print}}" x.txt
Теперь, что насчет оборотной стороны этого? Вы хотите распечатать строку, совпадающую с шаблоном, и одну или несколько строк перед перед ней, скажем, за 3 строки до «Строки 8».
awk "/Line 8/{for(i=1;i<=x;)print a[i++];print}{for(i=1;i<x;i++)a[i]=a[i+1];a[x]=$0;}" x=3 x.txt
Вышеупомянутое будет распечатано
Line 5 Line 6 Line 7 Line 8
Вот еще один полезный скрипт. Допустим, у вас есть два текстовых файла, и вы хотите сопоставить записи в обоих по ключу, а затем заменить каждую строку в файле2 соответствующей строкой с ключом из файла1. Пример поможет проиллюстрировать ситуацию.
Вам нужно заменить всю строку в файле 2.txt на основе ключа в файле 1.txt. В целях именования мы будем называть все до знака «=» ключа записи.
file1.txt ========= ui_home=/export/appl/website/${ui.root} java_home=/export/appl/java/ssss domain.host.list=server-1,server-2 domain.server.cluster.list=server-1:cluster1,server-2:cluster2 runtime=/export/appl/website/runtime ldap.provider.url=ldap://ldapserver:280 file2.txt ======== ui_home=/export/appl/ui/${test} java_home=/export/appl/java/zzzzz domain.host.list=server-10,server-12 domain.server.cluster.list=server-10:cluster1,server-12:cluster2 runtime=/export/appl/website/runtime ldap.provider.url=ldap://ldapserver:480 ai.home=/export/appl/ddss/shss
Результат, который мы хотим, показан ниже
new-file2.txt ============= ui_home=/export/appl/website/${ui.root} java_home=/export/appl/java/ssss domain.host.list=server-1,server-2 domain.server.cluster.list=server-1:cluster1,server-2:cluster2 runtime=/export/appl/website/runtime ldap.provider.url=ldap://ldapserver:280 ai.home=/export/appl/ddss/shss
Везде, где есть совпадающий «ключ записи» между файлом1 и файлом2, соответствующая запись файла2, содержащая этот ключ, заменяется соответствующей записью файла1. При отсутствии соответствующего ключа данные остаются неизменными.
Следующий awk-скрипт сделает это.
$ awk -F = -v OFS== 'FNR==NR{k[$1]=$2;next}$1 in k{$2=k[$1]}1' file1.txt file2.txt > new-file2.txt
И вот объяснение каждой из частей:
awk -F = # set FS ( Field Separator ) to "=" so automatically splits lines to key ( $1 ) - value ( $2 ) pairs -v OFS== # set OFS ( Output Field Separator ) to "=" so automatically place it between the fields on output ' FNR == NR { # FNR ( File Number of Records ) and NR ( Number of Records ) are equal only while processing the 1st input file k[$1] = $2 # store the key - value pair in array k next # jump to processing the next input record ( skip the rest of the code - it is for processing the 2nd input file ) } $1 in k { # current key has an entry in array k $2 = k[$1] # replace the current value with the matching one stored in array k } 1 # always perform default action ( print the current record ) ' file1.txt file2.txt > new-file2.txt # process our two input files and create our new output file
Мой последний пример — интересный вариант использования. Предположим, у вас есть большой файл, который вы хотите разделить на отдельные файлы меньшего размера на основе значения поля в большом файле, при этом файлы меньшего размера имеют значение этого поля в именах файлов. например, ваш большой файл выглядит так: -
bigfile.txt =========== Line 1|2|some other stuff Line 2|1|blah blah Line 3|8|blah blah Line 4|2|this is line 4 Line 5|8|this is line 5 Line 6|1|this is line 6
Вам нужно создать отдельные файлы, fileN.txt, где значение N основано на числовом значении во втором поле. В этом примере вы хотите создать файлы file1.txt, file2.txt и file8.txt. Кроме того, содержимое каждого созданного файла должно соответствовать строкам в файле большего размера. Вот один из способов сделать это.
$ awk -F"|" '{fname="file"$2".txt"} {print >fname}' bigfile.txt $ $ cat file1.txt Line 2|1|blah blah Line 6|1|this is line 6 $ $ cat file2.txt Line 1|2|some other stuff Line 4|2|this is line 4 $ $ cat file8.txt Line 3|8|blah blah Line 5|8|this is line 5
Это все для меня на данный момент. Если вам понравился этот контент, пожалуйста, поддержите меня аплодисментами и подпишитесь на меня, чтобы вскоре увидеть больше подобных вещей.
Если вы еще не являетесь средним участником и цените подобный контент, рассмотрите возможность присоединения по этой ссылке. Если вы это сделаете, я заработаю (очень) небольшую комиссию, которая поможет мне как писателю.