使用sed计算字符串的出现次数?

cho*_*hoc 16 sed

我有一个文件,其中包含多次写入的"标题".如何使用sed命令查找"title"在该文件中写入的次数,前提是"title"是一行中的第一个字符串?例如

# title
title
title
Run Code Online (Sandbox Code Playgroud)

应输出count = 2,因为第一行标题不是第一个字符串.

更新

我使用awk查找出现的总次数:

awk '$1 ~ /title/ {++c} END {print c}' FS=: myFile.txt
Run Code Online (Sandbox Code Playgroud)

但是,我怎么能告诉awk只计算那些标题为第一个字符串的行,如上例所示?

Pau*_*ce. 16

永远不要把话说绝了.纯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}
Run Code Online (Sandbox Code Playgroud)

说明:

#!/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
Run Code Online (Sandbox Code Playgroud)

以下是使用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$
Run Code Online (Sandbox Code Playgroud)

省略号表示此处省略的输出行.其上带有"11"的行是输出最终计数的地方.这是您在sedsed不使用调试器时获得的唯一输出.

  • @EdwardG:我同意这样做是荒谬的,但它回答了最初提出的问题。这是“拿着我的啤酒!”的完美例子。OP 在发布后不久就接受了[另一个答案](/sf/answers/124694741/)(不是我的)。在此期间,该问题的访问者对每个答案的投票程度不同。谁知道为什么我的收入会稍微多一点? (2认同)

pav*_*ium 12

我认为sed不合适,除非您在管道中使用它来转换文件,以便您需要的单词出现在单独的行上,然后用于grep -c计算出现次数.

我喜欢Jonathan tr用于将空格转换为换行符的想法.这种方法的优点在于连续的空格可以转换为多个空白行,但这并不重要,因为grep只能计算单词"title"的行.


Jon*_*ler 10

修改后的答案

简而言之,你不能 - sed不是工作的正确工具(它不能算).

sed -n '/^title/p' file | grep -c
Run Code Online (Sandbox Code Playgroud)

这将查找开始标题的行并打印它们,将输出提供给grep以计算它们.或者,等效地:

grep -c '^title' file
Run Code Online (Sandbox Code Playgroud)

原始答案 - 在编辑问题之前

简而言之,你不能 - 它不是这项工作的正确工具.

grep -c title file

sed -n /title/p file | wc -l
Run Code Online (Sandbox Code Playgroud)

第二个使用sed作为grep的代理,并将输出发送到'wc'来计算行数.两者都计算包含"标题"的行数,而不是标题的出现次数.你可以解决这个问题:

cat file |
tr ' ' '\n' |
grep -c title
Run Code Online (Sandbox Code Playgroud)

'tr'命令将空格转换为换行符,因此将每个空格分隔的单词放在它自己的行上,因此grep只计算包含单词标题的行.这是有效的,除非你有像'title-entitlement'这样的序列,其中没有空格分隔两次出现的标题.


gho*_*g74 5

sed 's/title/title\n/g' file | grep -c title
Run Code Online (Sandbox Code Playgroud)