我想知道如何通过一些文本处理实用程序计算每行中特定字符的数量?
例如,"在以下文本的每一行中进行计数
"hello!"
Thank you!
Run Code Online (Sandbox Code Playgroud)
第一行有两个,第二行有 0。
另一个例子是(在每一行中计数。
max*_*zig 129
你可以用sedand做到awk:
$ sed 's/[^"]//g' dat | awk '{ print length }'
2
0
Run Code Online (Sandbox Code Playgroud)
dat您的示例文本在哪里, sed 删除(对于每一行)所有非"字符并awk为每一行打印其大小(即length相当于length($0),其中$0表示当前行)。
对于另一个字符,您只需更改 sed 表达式。例如为了(:
's/[^(]//g'
Run Code Online (Sandbox Code Playgroud)
更新: sed对于这项任务来说有点矫枉过正 -tr就足够了。一个等效的解决方案tr是:
$ tr -d -c '"\n' < dat | awk '{ print length; }'
Run Code Online (Sandbox Code Playgroud)
意思是tr删除所有不在-c字符集中(意思是补码)的字符"\n。
Mar*_*ork 65
我只会用 awk
awk -F\" '{print NF-1}' <fileName>
Run Code Online (Sandbox Code Playgroud)
在这里,我们将字段分隔符(带有 -F 标志)设置为字符,"然后我们所做的就是打印字段数NF- 1。目标字符的出现次数将比分隔字段的数量少 1。
对于 shell 解释的有趣字符,您只需要确保对它们进行转义,否则命令行将尝试解释它们。因此,对于两者",)您都需要转义字段分隔符(使用\)。
Sté*_*nez 17
使用trard wc:
function countchar()
{
while IFS= read -r i; do printf "%s" "$i" | tr -dc "$1" | wc -m; done
}
Run Code Online (Sandbox Code Playgroud)
用法:
$ countchar '"' <file.txt #returns one count per line of file.txt
1
3
0
$ countchar ')' #will count parenthesis from stdin
$ countchar '0123456789' #will count numbers from stdin
Run Code Online (Sandbox Code Playgroud)
jos*_*hwb 12
awk如果匹配的数量太大(这恰好是我的情况),则使用的答案会失败。对于loki-astari的回答,报如下错误:
awk -F" '{print NF-1}' foo.txt
awk: program limit exceeded: maximum number of fields size=32767
FILENAME="foo.txt" FNR=1 NR=1
Run Code Online (Sandbox Code Playgroud)
对于从答案enzotib(并从等效manatwork),分段错误发生:
awk '{ gsub("[^\"]", ""); print length }' foo.txt
Segmentation fault
Run Code Online (Sandbox Code Playgroud)
maxschlepzig的sed解决方案工作正常,但速度很慢(时间如下)。
这里还没有提出一些解决方案。首先,使用grep:
grep -o \" foo.txt | wc -w
Run Code Online (Sandbox Code Playgroud)
并使用perl:
perl -ne '$x+=s/\"//g; END {print "$x\n"}' foo.txt
Run Code Online (Sandbox Code Playgroud)
以下是一些解决方案的一些时间安排(从最慢到最快的顺序);我把这里的东西限制为单行。'foo.txt' 是一个包含 84922 个匹配项的一行和一个长字符串的文件。
## sed solution by [maxschlepzig]
$ time sed 's/[^"]//g' foo.txt | awk '{ print length }'
84922
real 0m1.207s
user 0m1.192s
sys 0m0.008s
## using grep
$ time grep -o \" foo.txt | wc -w
84922
real 0m0.109s
user 0m0.100s
sys 0m0.012s
## using perl
$ time perl -ne '$x+=s/\"//g; END {print "$x\n"}' foo.txt
84922
real 0m0.034s
user 0m0.028s
sys 0m0.004s
## the winner: updated tr solution by [maxschlepzig]
$ time tr -d -c '\"\n' < foo.txt | awk '{ print length }'
84922
real 0m0.016s
user 0m0.012s
sys 0m0.004s
Run Code Online (Sandbox Code Playgroud)
enz*_*tib 11
然而,这不依赖于外部程序,在另一个实施bash,zsh,yash和一些实现/版本ksh:
while IFS= read -r line; do
line="${line//[!\"]/}"
echo "${#line}"
done <input-file
Run Code Online (Sandbox Code Playgroud)
使用line="${line//[!(]}"计数(。
Sté*_*las 11
另一种awk解决方案:
awk '{print gsub(/"/, "")}' <filename>
Run Code Online (Sandbox Code Playgroud)
awk 和 gsub 的另一种可能实现:
awk '{ gsub("[^\"]", ""); print length }' input-file
Run Code Online (Sandbox Code Playgroud)
该函数gsub相当于 sed 的's///g'。
使用gsub("[^(]", "")计数(。
我决定写一个 C 程序,因为我很无聊。
您可能应该添加输入验证,但除此之外都已设置。
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char c = argv[1][0];
char * line = NULL;
size_t len = 0;
while (getline(&line, &len, stdin) != -1)
{
int count = 0;
char * s = line;
while (*s) if(*s++ == c) count++;
printf("%d\n",count);
}
if(line) free(line);
}
Run Code Online (Sandbox Code Playgroud)
小智 6
对于字符串,最简单的方法是使用tr和wc(无需使用awk或过度使用sed)-但请注意上面关于tr, 计数字节而不是字符的注释-
echo $x | tr -d -c '"' | wc -m
Run Code Online (Sandbox Code Playgroud)
where$x是包含要评估的字符串(不是文件)的变量。