Contents

在Linux上计算一行或一个字段中的字符数

1. 概述

在之前的教程中,我们已经了解了如何计算文件中字符的出现次数 。 在本教程中,我们将了解如何计算一行或一个字段中的字符数。在结果中,我们还将打印行号以及字符数。

我们将使用 Linux 中一些最常用的命令来实现这一目标。

2. 问题

假设我们有以下文件:

$ cat items.txt
ID|Internal|Item|Type
1a|I|RAM|DDR4
2a|I|Processor|Intel
2b|E|Monitor|FHD
3b|E|Monitor|4K
4c|I|HDD|1TB
5c|I|SSD|512GB

在计算字符“E”时,我们期望得到这个结果:

Line Count
1	0
2	0
3	0
4	1
5	1
6	0
7	0

我们在第 4 行和第 5 行中有“E”字符。对于这些行,它打印了该字符的出现。

另一个用例是在特定字段中搜索字符。如果我们想在第二个字段中搜索“E”,我们将得到相同的结果。

3. 使用awk命令

首先,让我们检查一下如何使用awk 命令来计算字符数。众所周知,awk命令用于处理文本。它运行我们为文本处理指定的 AWK 语言。

使用awk命令,我们可以通过不同的方式实现这一点。

3.1. 使用 NR 和 NF 变量

一种方法是使用内置的 AWK 变量来计算每行中的字符数。我们知道NR 变量计算我们读过的行数。和 NF 变量计算字段的数量。

让我们看看实际情况:

$ awk -F 'E' 'BEGIN{print "Line", "\tCount"}{print NR "\t" NF-1}' items.txt
Line 	Count
1	0
2	0
3	0
4	1
5	1
6	0
7	0

在这里,我们使用字段分隔符作为搜索字符。然后,NF 变量跟踪字段数,NR 变量跟踪行号。我们为每一行打印这些以获得我们想要的输出。

为了在开始时打印一次标题,我们将它们放在BEGIN中。

3.2. 使用gsub函数

另一种方法是使用gsub函数。**此函数采用正则表达式模式、替换字符串和可选的目标记录。它返回替换的次数。**我们将此信息用作搜索字符的计数。

让我们看看它的实际效果:

$ awk 'BEGIN{print "Line", "\tCount"}{print NR "\t" gsub(/E/,"")}' items.txt
Line 	Count
1	0
2	0
3	0
4	1
5	1
6	0
7	0

在这里,我们再次使用了BEGIN块来打印标题。

然后我们使用gsub函数将字符替换为空字符串。在这里,我们的意图不是替换字符。但我们只对gsub函数的返回值感兴趣。返回的值为我们提供了字符出现的次数。将此计数与行号一起打印会为我们提供所需的输出。

3.3. 计算字段中的字符

我们可以使用gsub函数来计算特定字段中的字符数。在gsub函数中,我们将字段编号作为第三个参数传递。

让我们快速检查一下:

$ awk -F'|' 'BEGIN{print "Line", "\tCount"}{print NR "\t" gsub(/E/,"", $2)}' items.txt
Line 	Count
1	0
2	0
3	0
4	1
5	1
6	0
7	0

从上面的结果中,我们可以看到我们在第二个字段中打印了字符 E 的出现。命令几乎相同。唯一的区别是我们使用*-F选项将字段分隔符设置为竖线 (|) 字符。而在gsub*函数中,我们将目标字段作为要搜索的字段编号。

4. 使用cat , cut , tr命令

接下来,让我们看看如何使用catcuttr 命令来计算字符数。

让我们直接进入它:

$ cat items.txt | tr -c -d "E\n" | cat -n
  | { echo -e "Line" "\tCount"; while read num data; do printf "%d\t%d\n" $num ${#data}; done; }
Line 	Count
1	0
2	0
3	0
4	1
5	1
6	0
7	0

在这里,我们在管道中使用了命令。我们使用cat命令读取文件内容。然后我们将结果通过管道传递给tr命令。在那里,我们结合了 -c 选项和*-d选项来补充搜索,而不是删除我们正在搜索的字符。因此,我们得到每行带有搜索字符的结果。然后使用带有-n选项的cat*命令,我们输入行号。

最后,在最后一个管道中,我们得到了打印标题并计算每行字符数的代码。

4.1. 计算字段中的字符

现在,如果我们需要在特定字段中搜索字符,我们可以在管道的开头使用cut命令。

让我们看一下:

$ cut -d '|' -f 2 items.txt | tr -c -d "E\n" | cat -n
  | { echo -e "Line" "\tCount"; while read num data; do printf "%d\t%d\n" $num ${#data}; done; }
Line 	Count
1	0
2	0
3	0
4	1
5	1
6	0
7	0

这与上面的命令相同。我们没有在开始时使用cat命令,而是使用cut命令仅提取第二个字段。

让我们看看用于cut命令的不同选项:

  • -d | : 将分隔符用作 |
  • -f 2 : 分割后取第二个字段

一旦我们提取了第二个字段,它就会传递给管道。该命令的其余部分与上述命令相同。我们得到了我们想要的结果。

5. 使用 Bash 脚本

每当我们需要自动化我们的任务时,Bash 脚本都很方便。让我们使用 Bash 脚本来计算字符数。我们已经在文件count.sh中准备好了脚本。

让我们看一下:

$ cat count.sh 
line=1
echo -e "Line\tCount"
while read -a array_data
do
    data=${array_data[0]}
    new_data=${data//$1/}
    count=$((${#data}-${#new_data}))
    printf "%d\t%d\n" $((line++)) $count
done < $2
$ ./count.sh E items.txt 
Line	Count
1	0
2	0
3	0
4	1
5	1
6	0
7	0

正如我们所见,Bash 脚本接受两个参数。它们是要搜索的字符和文件名。

首先,在脚本中,我们使用 while 循环逐行读取文件。该行存储在变量array_data中。然后我们替换该行中的字符并将其存储到另一个变量new_data中。现在我们得到了原始行和没有搜索字符的行。有了这个,我们计算了这些变量的字符串长度的差异。这将为我们提供该行中搜索字符的数量。然后,我们将其与行号一起打印。最后,我们对所有行重复此操作。

从上面的结果可以看出,它已经统计了每一行的字符数。

6. 使用grep命令

有时,我们只想打印那些具有我们需要找到的字符的行。对于这些情况,我们可以使用grep 命令。

让我们看看它的实际效果:

$ echo "Count  Line"; grep -n -o "E" items.txt | sort -n | uniq -c | cut -d : -f 1
Count  Line
      1 4
      1 5

在这里,我们使用了带有*-n选项的grep命令来打印行号。通过使用-o*选项,它只打印匹配的字符。

然后我们对grep命令的结果进行排序。我们使用带有*-c选项的uniq命令计算搜索字符的出现次数。最后,我们使用cut*命令从最终结果中删除不需要的字符串。

通过使用 grep命令,我们可以只打印需要的内容。在搜索包含大量行的大文件时,这将很有帮助。