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

使用sed计算字符串的出现次数?,sed,Sed,我有一个文件,其中包含多次写入的“标题”。如果“title”是一行中的第一个字符串,那么如何使用sed命令查找在该文件中写入“title”的次数?e、 g # title title title 应输出计数=2,因为第一行中的标题不是第一个字符串 更新 我使用awk查找事件总数,如下所示: awk '$1 ~ /title/ {++c} END {print c}' FS=: myFile.txt 但是,我如何告诉awk只计算上面示例中解释的第一个字符串为title的行呢?我认为sed不合适

我有一个文件,其中包含多次写入的“标题”。如果“title”是一行中的第一个字符串,那么如何使用sed命令查找在该文件中写入“title”的次数?e、 g

# title
title
title
应输出计数=2,因为第一行中的标题不是第一个字符串

更新

我使用awk查找事件总数,如下所示:

awk '$1 ~ /title/ {++c} END {print c}' FS=: myFile.txt

但是,我如何告诉awk只计算上面示例中解释的第一个字符串为title的行呢?

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

我喜欢乔纳森使用
tr
将空格转换为换行符的想法。这种方法的美妙之处在于,连续的空格被转换成多个空行,但这并不重要,因为
grep
将能够只计算带有单个单词“title”的行。

修改后的答案 简而言之,您不能-sed不是用于该作业的正确工具(它不能计数)

这将查找以标题开头的行并打印它们,将输出输入到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只能对包含单词标题的行进行计数。除非您有“标题授权”之类的序列,其中没有空格分隔两个出现的标题。

只需一个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

永远不要说永远。纯
sed
(尽管可能需要GNU版本)

说明:

#!/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
以下是使用以下方法对脚本进行跟踪的摘录:


省略号表示我在这里省略的输出行。带有“11”的行本身就是输出最终计数的地方。这是在未使用
sedsed
调试器时得到的唯一输出。

这可能适用于您:

sed '/^title/!d' file | sed -n '$='

以15秒的优势击败我-太棒了。我应该少唠叨了。我想我应该离开塞德。也许awk会为我变魔术。请看更新的问题。我如何计算标题为第一个字符串的行数?这将使总数为:3在你的例子中,因为问题发生了变化(可能是在你回答的时候),所以不再需要计算标题在一行中任何地方出现的次数-只计算行首出现的次数。@Johnathan,这不重要。这种方法可以做到这一切。如果要求更改为处处都计算“标题”,则代码的更改最小。搜索模式/^title/在行首查找标题。使用“
grep-c”^title“
”也比awk简单;也可能更快。更改正则表达式以匹配行首:/^title/非常感谢。格雷普肯定更简单。谢谢你,Samuel。顺便说一下,只计算以“title”开头的行的关键是使用正则表达式锚定:
/^title/
,其中
^
表示行的开头。类似地,
$
表示与
/book$/
中相同的行的结尾,它与以“book”结尾的行相匹配。如果你想匹配整行,你可以使用两个锚定:
/^书名$/
,这与“这本书的书名是战争与和平”不匹配。这与乔纳森·莱夫勒答案的第一部分基本相同。是的,看起来很相似,但不完全相同。在sed中使用不同的方法。我希望得到一个解释。@ThomasGHenry:我添加了一个解释
#!/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
$ 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$
sed '/^title/!d' file | sed -n '$='