Считать количество случаев строки с помощью sed?

Посмотрите на помощника и команды ftype в поле DOS. Вот пример для .jpg на моей машине

c:\>assoc .jpg
.jpg=jpegfile

c:\>ftype jpegfile
jpegfile="C:\Program Files\Common Files\Microsoft Shared\PhotoEd\PHOTOED.EXE" "%1"

assoc .sh=bashscript

ftype bashscript="c:\cygwin\bin\bash.exe" "%1"

, Удостоверяются, что Вы изменяете путь для избиения ftype команда для соответствия, где Вы имеете cygwin , установил

16
задан Jonathan Leffler 23 November 2009 в 06:15
поделиться

5 ответов

Я не думаю, что sed будет подходящим, если вы не используете его в конвейере для преобразования файла, чтобы нужное слово отображалось в отдельных строках, а затем используйте grep -c для подсчета вхождений.

Мне нравится идея Джонатана использовать tr для преобразования пробелов в символы новой строки. Прелесть этого метода в том, что последовательные пробелы преобразуются в несколько пустых строк , но это не имеет значения , потому что grep сможет подсчитать только строки с одним словом 'title' .

12
ответ дан 30 November 2019 в 15:56
поделиться

Никогда не говори никогда. Чистый 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 не используется.

16
ответ дан 30 November 2019 в 15:56
поделиться
sed 's/title/title\n/g' file | grep -c title
3
ответ дан 30 November 2019 в 15:56
поделиться

Исправленный ответ

Вкратце, вы не можете - 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 может подсчитывать только строки, содержащие заголовок слова. Это работает, если у вас нет последовательностей, таких как «название-право», где нет пробела, разделяющего два вхождения названия.

10
ответ дан 30 November 2019 в 15:56
поделиться

подойдет всего одна команда 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

если вы хотите просто «title» в качестве первой строки, используйте « == "вместо ~

awk '$1 == "title"{++c}END{print c}' file
3
ответ дан 30 November 2019 в 15:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: