如何获取字符串特定部分的唯一计数

如何获取字符串特定部分的唯一计数

我在一个文件中有一组数据。

psf7433-nlhrms
unit7433-nobody
unit7333-opera
bpx7333-operations
app7333-osm
unit7330-partners
psf7331-pdesmond
unit7333-projm
mnp7330-redirect
unit7333-retailbanking
cpq7333-rkarmer
unit6333-sales
ring7323-support
unit7133-telco
post7323-uadb
sun7335-ukhrms
burp7133-wfnmreply

如何忽略每行中的起始字母字符和数字后面的字符并获取唯一数字的计数。 (或)如何仅检索每行中的数值并获取其唯一计数。

考虑到我们设法只提取数值,我们会得到这个。

7433
7433
7333
7333
7333
7330
7331
7333
7330
7333
7333
6333
7323
7133
7323
7335
7133

现在,我想要检索到的数值的唯一计数。因此,忽略重复,我应该得到以下最终输出。

8

我无法通过使用来做到这一点awk或者sed甚至简单查询 |切

我不需要提取值的列表,我只想要最终的计数作为答案。

帮我!

答案1

使用grep,仅过滤掉数字:

grep -Eo '[0-9]+-' file | sort -u | wc -l
  • [0-9]匹配 0 到 9 之间的任何字符(任何数字)。
  • +扩展正则表达式代表至少一个字符(这就是该-E选项与 一起使用的原因grep)。 So[0-9]+-匹配一位或多位数字,后跟-.
  • -o仅打印与您的模式匹配的部分,因此给定输入abcd23-gf56grep将仅打印23-
  • sort -u排序和过滤唯一条目(由于-u),并wc -l计算输入中的行数(因此,唯一条目的数量)。

答案2

您可以使用:

tr -dc '\-0-9\n' | sort -u -t- -nk1,1 | grep -c .

...诚然,这不仅仅是受到穆鲁在这里的回答的启发。但不同的是,我习惯grep对行进行计数,而不是wc在输入中有空行的情况下进行计数。他的答案没有空行问题,因为grep -o只会打印匹配的行grep -c这里只计算它们), 但tr 打印空行,因为换行符是它不会删除的少数字符之一。这意味着输入中任意数量的空行都会使wc结果倾斜 1。

因此,tr这里的效率可能比计数部门高,grep -o但可能wc会击败grep计数部门。我喜欢这种方式,我认为是出于可移植性的原因,也因为我通常尝试首先使用最有效的过滤器来修剪数据,然后在链中稍后使用效率较低的过滤器。

这让我们可以根据在ab 分隔符上分割的数字排序来选择在其独特排序sort中将考虑的每行位数。删除其输入中任何数字、破折号或换行符字节的补码。这样 - 只要没有出现破折号-u-n-k-t-tr -d-c-您想要比较的数字字符串,那么任何行中唯一剩下的就是:

#nothing at all

...或者...

[numbers]

...或者...

[numbers]-[more numbers]more-dashes-...

因此,当输出通过管道传输时,sort我们指示它仅比较破折号之前出现的数字字符串(如果有)。这样,无论是否是破折号,唯一重要的数字就是您想要计算的数字。

然后我们grep -c计算至少包含一个.字符的行。以下命令打印8

tr -dc '\-0-9\n' <<\IN | sort -u -t- -nk1,1 | grep -c .
psf7433-nlhrms
unit7433-nobody
unit7333-opera
bpx7333-operations
app7333-osm
unit7330-partners
psf7331-pdesmond
unit7333-pro-09-0jm
mnp7330-redir09o-0ect
unit7333-retailbanking
cpq7333-rkarmer
unit6333-sales
ring7323-support


unit7133-telco
post7323-uadb
sun7335-ukhrms
burp7133-wfnmreply
IN

答案3

使用扩展 grep 查找四位数字,告诉 grep 仅列出匹配项(而不是默认的整行):

grep -Eo '[0-9]+' <filename>

对此数字列表进行排序并仅输出唯一的数字:

sort -u

计算行数:

wc -l

把它们放在一起:

$ grep -Eo '[0-9]+' filename | sort -u | wc -l
8

答案4

一个awk解决方案

awk -F'-' '{sub(/[^[:digit:]]+/, "", $1); a[$1]} END{for (k in a) ++i; print i}' file
8

相关内容