我想知道如何通过某些文本处理实用程序来计算每行中特定字符的数量?
例如,计算"
以下文本的每一行
"hello!"
Thank you!
第一行有两个,第二行有0。
(
另一个例子是对每一行进行计数。
答案1
您可以使用 和sed
来做到这一点awk
:
$ sed 's/[^"]//g' dat | awk '{ print length }'
2
0
dat
您的示例文本在哪里,sed 删除(对于每行)所有非"
字符并awk
为每行打印其大小(即length
相当于length($0)
,其中$0
表示当前行)。
对于另一个字符,您只需更改 sed 表达式即可。例如对于(
:
's/[^(]//g'
更新: sed
对于这项任务来说有点矫枉过正了——tr
已经足够了。等效的解决方案tr
是:
$ tr -d -c '"\n' < dat | awk '{ print length; }'
意思是tr
删除所有不在-c
字符集中的字符(表示补码)"\n
。
答案2
我只会使用 awk
awk -F\" '{print NF-1}' <fileName>
这里我们将字段分隔符(使用 -F 标志)设置为字符,"
然后我们所做的就是打印字段数NF
- 1。目标字符的出现次数将比分隔字段的数量少 1。
对于 shell 解释的有趣字符,您只需要确保对它们进行转义,否则命令行将尝试解释它们。因此,对于两者"
,)
您都需要转义字段分隔符(使用\
)。
答案3
使用tr
阿德wc
:
function countchar()
{
while IFS= read -r i; do printf "%s" "$i" | tr -dc "$1" | wc -m; done
}
用法:
$ 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
答案4
awk
如果匹配的数量太大(这恰好是我的情况),则使用失败的答案。对于来自的答案洛基阿斯塔里,报如下错误:
awk -F" '{print NF-1}' foo.txt
awk: program limit exceeded: maximum number of fields size=32767
FILENAME="foo.txt" FNR=1 NR=1
对于来自的答案恩佐替布(以及相当于工作的人),出现分段错误:
awk '{ gsub("[^\"]", ""); print length }' foo.txt
Segmentation fault
解决方案sed
通过马克斯施莱普齐格工作正常,但速度很慢(时间如下)。
此处尚未建议一些解决方案。首先,使用grep
:
grep -o \" foo.txt | wc -w
并使用perl
:
perl -ne '$x+=s/\"//g; END {print "$x\n"}' foo.txt
以下是一些解决方案的时间安排(从最慢到最快排序);我在这里只讲了一些话。 '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