统计匹配模式的行数,但仅限第一次出现

0 投票
4 回答
951 浏览
提问于 2025-04-20 10:41

我有一个文件,里面有很多行和各种内容。有些行是以特定的模式开头的,这种模式可能会重复出现。例如:

some line
some line
this: idA001 text
this: idA002 text
some line
this: idB001 text
this: idA001 text
this: idA002 text
this: idC001 text
...

我想要统计每个以 this: id* 开头的第一次出现的行……

如果我用 cat file | grep "this: " | wc -l,我会统计到每一次出现……我需要写一个脚本,先过滤出这些行,然后去掉重复的,还是说可以用一条简单的命令在bash里完成?如果需要脚本的话,我更喜欢用Python或者Bash……

4 个回答

-1

这是一个简单的解决方案:

my_words = ['this: id']
a = set()
with open('got.txt') as f:
    for line in f:
    if any(word in line for word in my_words):
            a.add(line)
print len(a)

我做了什么:我把包含'this: id'的行写进了一个集合里。因为集合只包含唯一的值,所以你的问题就解决了。这就是集合的一个实际用途。

1

我们可以用一行代码这样写

len({i for i in file if i.startswith('this :id')})
2

这样做就可以了:

awk '/^this:/ && !seen[$0]++ {a++} END {print a}' file
4

它会计算有多少不重复的行是以 this: 开头的。

2

如果你想用一行命令在bash里做到这一点:

sort < file | uniq | grep "this: " | wc -l

uniq这个命令可以去掉重复的行。

但是我们想要过滤掉那些不一定相邻的重复行,所以我们首先需要用sort进行排序。

后面的部分和你原来的命令是一样的。

在最近的*nix系统中(我想这包括你可能会用到的任何系统),你可以把sortuniq的调用合并成一个sort -u。另外,正如jm666提到的,grep -c会输出匹配行的数量,而不是匹配的行,所以你不需要wc。这样整个命令就变成:

sort -u < file | grep -c "this: "

最后一点:如果你只想要以this:开头的行,而不是包含它的任何行,你可以在你的grep表达式中使用^这个特殊字符,它只匹配行的开头,像这样:

sort -u < file | grep -c "^this: "

撰写回答