Подсчитайте количество вхождений строки с помощью sed?
у меня есть файл, который содержит "заголовок" написано много раз. Как я могу найти количество раз, когда" title "записывается в этом файле с помощью команды sed при условии, что" title " является первой строкой в строке? например,
# title
title
title
должен выводить count = 2, потому что в первой строке заголовок не является первой строкой.
обновление
я использовал awk, чтобы найти общее число вхождений, как:
awk ' ~ /title/ {++c} END {print c}' FS=: myFile.txt
но как я могу сказать awk считайте только те строки, имеющие заголовок первая строка как описано в вышеприведенном примере?
6 ответов
не думаю sed
было бы уместно, если вы не используете его в конвейере для преобразования вашего файла, чтобы слово, которое вам нужно, появилось в отдельных строках, а затем используйте grep -c
для подсчета вхождений.
мне нравится идея Джонатана использовать tr
для преобразования пробелов в новые строки. Красота этого метода заключается в том, что последовательные пробелы преобразуются в несколько пустых строк но это не важно, потому что grep
будет иметь возможность подсчитывать только строки с одним слово "титул".
никогда не говори никогда. Чистый sed
(хотя для этого может потребоваться версия GNU).
#!/bin/sed -nf
# based on a script from the sed info file (info sed)
# section 4.8 Numbering Non-blank Lines (cat -b)
# modified to count lines that begin with "title"
/^title/! be
x
/^$/ s/^.*$/0/
/^9*$/ s/^/0/
s/.9*$/x&/
h
s/^.*x//
y/0123456789/1234567890/
x
s/x.*$//
G
s/\n//
h
:e
$ {x;p}
пояснение:
#!/bin/sed -nf
# run sed without printing output by default (-n)
# using the following file as the sed script (-f)
/^title/! be # if the current line doesn't begin with "title" branch to label e
x # swap the counter from hold space into pattern space
/^$/ s/^.*$/0/ # if pattern space is empty start the counter at zero
/^9*$/ s/^/0/ # if pattern space starts with a nine, prepend a zero
s/.9*$/x&/ # mark the position of the last digit before a sequence of nines (if any)
h # copy the marked counter to hold space
s/^.*x// # delete everything before the marker
y/0123456789/1234567890/ # increment the digits that were after the mark
x # swap pattern space and hold space
s/x.*$// # delete everything after the marker leaving the leading digits
G # append hold space to pattern space
s/\n// # remove the newline, leaving all the digits concatenated
h # save the counter into hold space
:e # label e
$ {x;p} # if this is the last line of input, swap in the counter and print it
вот выдержки из следа скрипта с использованием sedsed:
$ echo -e 'title\ntitle\nfoo\ntitle\nbar\ntitle\ntitle\ntitle\ntitle\ntitle\ntitle\ntitle\ntitle' | sedsed-1.0 -d -f ./counter
PATT:title$
HOLD:$
COMM:/^title/ !b e
COMM:x
PATT:$
HOLD:title$
COMM:/^$/ s/^.*$/0/
PATT:0$
HOLD:title$
COMM:/^9*$/ s/^/0/
PATT:0$
HOLD:title$
COMM:s/.9*$/x&/
PATT:x0$
HOLD:title$
COMM:h
PATT:x0$
HOLD:x0$
COMM:s/^.*x//
PATT:0$
HOLD:x0$
COMM:y/0123456789/1234567890/
PATT:1$
HOLD:x0$
COMM:x
PATT:x0$
HOLD:1$
COMM:s/x.*$//
PATT:$
HOLD:1$
COMM:G
PATT:\n1$
HOLD:1$
COMM:s/\n//
PATT:1$
HOLD:1$
COMM:h
PATT:1$
HOLD:1$
COMM::e
COMM:$ {
PATT:1$
HOLD:1$
PATT:title$
HOLD:1$
COMM:/^title/ !b e
COMM:x
PATT:1$
HOLD:title$
COMM:/^$/ s/^.*$/0/
PATT:1$
HOLD:title$
COMM:/^9*$/ s/^/0/
PATT:1$
HOLD:title$
COMM:s/.9*$/x&/
PATT:x1$
HOLD:title$
COMM:h
PATT:x1$
HOLD:x1$
COMM:s/^.*x//
PATT:1$
HOLD:x1$
COMM:y/0123456789/1234567890/
PATT:2$
HOLD:x1$
COMM:x
PATT:x1$
HOLD:2$
COMM:s/x.*$//
PATT:$
HOLD:2$
COMM:G
PATT:\n2$
HOLD:2$
COMM:s/\n//
PATT:2$
HOLD:2$
COMM:h
PATT:2$
HOLD:2$
COMM::e
COMM:$ {
PATT:2$
HOLD:2$
PATT:foo$
HOLD:2$
COMM:/^title/ !b e
COMM:$ {
PATT:foo$
HOLD:2$
. . .
PATT:10$
HOLD:10$
PATT:title$
HOLD:10$
COMM:/^title/ !b e
COMM:x
PATT:10$
HOLD:title$
COMM:/^$/ s/^.*$/0/
PATT:10$
HOLD:title$
COMM:/^9*$/ s/^/0/
PATT:10$
HOLD:title$
COMM:s/.9*$/x&/
PATT:1x0$
HOLD:title$
COMM:h
PATT:1x0$
HOLD:1x0$
COMM:s/^.*x//
PATT:0$
HOLD:1x0$
COMM:y/0123456789/1234567890/
PATT:1$
HOLD:1x0$
COMM:x
PATT:1x0$
HOLD:1$
COMM:s/x.*$//
PATT:1$
HOLD:1$
COMM:G
PATT:1\n1$
HOLD:1$
COMM:s/\n//
PATT:11$
HOLD:1$
COMM:h
PATT:11$
HOLD:11$
COMM::e
COMM:$ {
COMM:x
PATT:11$
HOLD:11$
COMM:p
11
PATT:11$
HOLD:11$
COMM:}
PATT:11$
HOLD:11$
многоточие представляет строки вывода, которые я опустил здесь. Строка с "11" на ней сама по себе является тем местом, где выводится конечный счет. Это единственный результат, который вы получите, когда sedsed
отладчик не используется.
пересмотренный ответ
кратко, вы не можете-sed не является правильным инструментом для работы (он не может рассчитывать).
sed -n '/^title/p' file | grep -c
это ищет строки, начинающие заголовок и печатает их, подавая вывод в grep, чтобы подсчитать их. Или, эквивалентно:
grep -c '^title' file
оригинальный ответ-до того, как вопрос был отредактирован
лаконично, вы не можете - это не правильный инструмент для работы.
grep -c title file
sed -n /title/p file | wc -l
второй использует sed в качестве суррогата для grep и отправляет вывод в " wc " для подсчета строк. Оба подсчитывают количество строк, содержащих "заголовок", а не количество вхождений заголовка. Вы можете исправить это с помощью чего-то вроде:
cat file |
tr ' ' '\n' |
grep -c title
команда 'tr' преобразует пробелы в новые строки, таким образом, помещая каждое слово, разделенное пробелом, в свою собственную строку, и поэтому grep получает только количество строк, содержащих название слова. Это работает, если у вас нет последовательностей, таких как "title-entitlement", где нет пространства, разделяющего эти два вхождения титула.
достаточно одной команды gawk. Не используйте grep-c, потому что он подсчитывает только строку с "title" В ней, независимо от того, сколько "title"есть в строке.
$ more file
# title
# title
one
two
#title
title title
three
title junk title
title
four
fivetitlesixtitle
last
$ awk '!/^#.*title/{m=gsub("title","");total+=m}END{print "total: "total}' file
total: 7
Если вы просто хотите "название" в качестве первой строки, используйте "==" вместо ~
awk ' == "title"{++c}END{print c}' file