$ awk '/Bond/{c++; print "There is a match on line " NR} END{print "\"Bond\" appeared " c " times in the file " FILENAME}' bond.txt
There is a match on line 1
There is a match on line 8
"Bond" appeared 2 times in the file bond.txt
awk неявно перебирает все входные строки.
/Bond/{c++; print "There is a match on line " NR}
Для строк, соответствующих регексу Bond
, счетчик c
увеличивается и выводится сообщение, показывающее, в какой строке находится совпадение. В awk количество прочитанных на данный момент строк равно NR
.
END{print "\"Bond\" появился " c " раз в файле " FILENAME}
После чтения последней строки выводится сообщение с общим количеством совпадений.
Для тех, кто любит, чтобы код располагался на многих строках:
awk '
/Bond/{
c++
print "There is a match on line " NR
}
END{
print "\"Bond\" appeared " c " times in the file " FILENAME
}
' bond.txt
Этот подход читает файл дважды. В первый раз выводится версия файла, отформатированная с номерами строк. Во второй раз выводится итоговый вывод:
$ awk 'FNR==NR{printf("%5d) %s\n", NR,$0);next} /Bond/{c++; print "There is a match on line " FNR} END{print "\"Bond\" appeared " c " times in the file " FILENAME}' bond.txt{,}
1) Secret agent Bond had been warned not to tangle with Goldfinger.
2) But the super-criminal's latest obsession was too strong, too dangerous.
3) He had to be stopped.
4) Goldfinger was determined to take possession of half the supply of
5) mined gold in the world--to rob Fort Knox!
6) For this incredible venture he had enlisted the aid of the top
7) criminals in the U.S.A, including a bevy of beautiful thieves from the
8) Bronx. And it would take all of Bond's unique talents to make it fail--
9) as fail it must.
There is a match on line 1
There is a match on line 8
"Bond" appeared 2 times in the file bond.txt
Приведенный выше вариант отличается от первого двумя особенностями. Во-первых, в командной строке файл указан дважды как bond.txt bond.txt
или, используя трюк bash расширение скобок, как bond.txt{,}
.
Во-вторых, мы добавили команду:
FNR==NR{printf("%5d) %s\n", NR,$0);next}
Эта команда выполняется только если FNR==NR
, где NR - общее количество прочитанных строк, а FNR - количество строк, прочитанных из текущего файла. Таким образом, когда FNR==NR
, мы читаем файл в первый раз. Затем мы printf
форматируем вывод и переходим к следующей
строке, пропуская остальные команды сценария.
В этом варианте мы читаем файл только один раз, печатая отформатированную версию и сохраняя итоговую информацию для печати в конце:
$ awk '{printf("%5d) %s\n", NR,$0)} /Bond/{c++; s=s ORS "There is a match on line " FNR} END{print s; print "\"Bond\" appeared " c " times in the file " FILENAME}' bond.txt
1) Secret agent Bond had been warned not to tangle with Goldfinger.
2) But the super-criminal's latest obsession was too strong, too dangerous.
3) He had to be stopped.
4) Goldfinger was determined to take possession of half the supply of
5) mined gold in the world--to rob Fort Knox!
6) For this incredible venture he had enlisted the aid of the top
7) criminals in the U.S.A, including a bevy of beautiful thieves from the
8) Bronx. And it would take all of Bond's unique talents to make it fail--
9) as fail it must.
There is a match on line 1
There is a match on line 8
"Bond" appeared 2 times in the file bond.txt
Похоже, что это просто конвейер, вторая часть которого представляет собой пустую команду, содержащую только перенаправление. Запись в виде date | >file
может упростить интерпретацию. Пустая команда ничего не делает, кроме как обрабатывает перенаправление, создавая файл.
date >| file
, с другой стороны, будет действовать как переопределение параметра оболочки noclobber
, который предотвращает перезапись существующих файлов обычным >
.
$ touch foo; set -o noclobber
$ date > foo
bash: foo: cannot overwrite existing file
$ date >| foo # works
Да, это не приведет к ошибке, потому что для bash > file
означает перенаправление в файл с именем file
. Поскольку в вашем случае нечего перенаправлять в файл, bash просто создаст имя файла file
, в котором ничего нет.
[bd@centos-6.5 my-tests]$ date | > my_file
[bd@centos-6.5 my-tests]$ cat my_file
[bd@centos-6.5 my-tests]$