Как посчитать вхождение конкретной строки в определенную строку в файле?
Я знаю, что могу использовать wc, чтобы вернуть общее количество слов (и строк) в файле, используя:
wc <filename>
Есть ли способ вернуть количество для определенной строки в определенной строке файла?
Что-то вроде следующего:
wc -<flag> <line number> -<flag> <string> <filename>
5 ответов
Это нужно сделать в три этапа:
Выберите номер строки N (пример использует строку 42):
sed '42!d'
Поиск строки для всех вхождений определенного шаблона (здесь строка / регулярное выражение
hello
) и распечатайте их отдельно:grep -o 'hello'
Подсчитать совпадения:
wc -l
Или поместить его в один командный канал, читая из file.txt
:
sed '42!d' file.txt | grep -o 'hello' | wc -l
Это хороший пример использования инструментов Unix в конвейере.
line=5
str="ipsum"
sed -n "${line}p" filename | grep -o -- "$str" | wc -l
Сед p
Команда выводит заданную строку файла и передает ее в grep. Grep-х -o
опция говорит ему выводить все совпадения для данной строки, и каждое совпадение выводится в отдельной строке. Вывод Grep подается на wc, который считает количество строк.
питон
Вот один из способов сделать это в Python через понимание списка (см. Ниже альтернативную более короткую версию).
$ python -c 'import sys;print([ l for i,l in enumerate(sys.stdin,1) if i==2][0].count("word"))' < input.txt
3
$ cat input.txt
nothing here
word and another word, and one more word
last line
Как это работает:
- мы запускаем интерпретатор Python с
-c
флаг, где команды содержатся в одинарных кавычках; - входной файл
input.txt
перенаправлен вstdin
поток интерпретатора Python через<
оператор оболочки. Следовательно, нам нужноsys
модуль. - Использование структуры понимания списка
[something for item in something]
мы читаем строки текста изsys.stdin
, enumerate(sys.stdin,1)
позволяет нам подсчитать, перечислить строки, т.е. с каждой итерацией понимания списка, мы получим строку текста вl
переменная и индекс вi
переменная, начиная отсчет с 1.i==2
отфильтрует только строку, индекс которой равен 2. Вот так мы узнаем, какую строку извлечь.- Таким образом, в результате наш список будет содержать только один элемент, а в списке его индекс
0
, Итак, мы ссылаемся на этот пункт как[<list comprehension stuff here>][0]
, -The.count("word")
это то, что на самом деле делает счет. По определению он возвращает количество непересекающихся вхождений подстроки в строке. - наконец, все это содержалось в
print()
заявление. Так что какой бы номер.count()
возврат метода будет отображаться на экране.
Более короткая версия
Более короткий способ сделать то же самое в Python будет использовать readlines()
метод вместо понимания списка, и обратитесь к конкретному элементу в списке, который readlines()
производит. Обратите внимание, что readlines()
создает список, а списки в Python индексируются 0, что означает, что если вы хотите прочитать строку x, вы должны ссылаться на элемент списка x-1. Например,
$ python -c 'import sys;print(sys.stdin.readlines()[1].count("word"))' < input.txt
3
СЕПГ + Grep
Конечно, нам не нужно придерживаться только языков сценариев. sed
а также grep
предоставить достаточно инструментов, которые мы можем использовать для удовлетворения наших потребностей. С grep -c
мы можем подсчитать вхождение совпадающих строк, поэтому все, что нам нужно сделать, - это выделить нужную нам строку и разбить все слова в этой строке на отдельные строки. Вот так:
$ sed -n '2{s/ /\n/g;p}' input.txt | grep -c 'word'
3
awk
решение:
awk 'NR==X { print gsub("word",""); }' file
- изменить
X
с вашим конкретным номером строки. - измените "слово" с вашим желаемым словом.
gsub
возвращает номер замены "слова", похоже, мы его считаем.
Exampe:
$ cat file:
a b c a a d
d e f f f 1
давайте посмотрим, сколько 'f' мы получили в строке "2":
$ awk 'NR==2 { print gsub("f",""); }' file
3
Один из способов сделать это, в perl
:
perl -lne '
BEGIN{($lineno, $str) = splice @ARGV,0,2}
print $c = () = /$str/g if $. == $lineno
' <lineno> <string> <filename>