我正在尝试数辅音的出现在多个文件,但我希望单独计算每个文件的出现次数。我用
awk -v FS="" '{for ( i=1;i<=NF;i++){if($i ~/[bcdfghjklmnpqrtsvwxyzBCDEFGHJKLMNPQRTSVWXYZ]/) count_c++}} END {print FILENAME,count_c}' file1 file2
file1 看起来像这样:
bac Dfeg
k87 eH
tRe
rt up
file2 如下所示:
hi
rt2w
Prt
但它会打印两个文件的出现次数(output= file2 19
)。我怎样才能改变它,使输出如下:
file1 12
file2 7
答案1
使用 GNU awk 处理 ENDFILE 和 IGNORECASE:
$ awk -v IGNORECASE=1 '
{ cnt += ( gsub(/[[:alpha:]]/,"&") - gsub(/[aeiou]/,"&") )}
ENDFILE { print FILENAME, cnt+0; cnt=0 }
' file1 file2
file1 12
file2 7
或使用任何 POSIX awk:
$ awk '
{ lc=tolower($0); cnt[FILENAME] += (gsub(/[[:alpha:]]/,"&",lc) - gsub(/[aeiou]/,"&",lc)) }
END { for (i=1; i<ARGC; i++) print ARGV[i], cnt[ARGV[i]]+0 }
' file1 file2
file1 12
file2 7
如果您只想计算特定字符 b、c、d 等,而不是所有非 aeiou 的字母字符,那么只需将( gsub(/[[:alpha:]]/,"&") - gsub(/[aeiou]/,"&") )
上面更改为gsub(/[bcdfghjklmnpqrtsvwxyz]/,"&"))
请注意,与在子句中打印结果的任何方法不同FNR==1
,上述两个脚本都将通过打印文件名和 0 作为计数来正确处理空文件。
另请注意cnt+0
第一个脚本中的 -如果第一个文件为空+0
,则确保打印的值将是数字0
而不是空字符串。
如果相同的文件名可以在输入中出现多次,则FNR==1{cnt[FILENAME]=0}
如果您希望其输出多次,则添加到脚本的开头;if (!seen[ARGV[i]]++) { ... }
如果您只想输出一次,则在 END 部分的打印周围添加。
看https://unix.stackexchange.com/a/642372/133219来回答同样计算元音的后续问题。
答案2
FWIW,可能不多,如果没有awk
:我会很想这样做:
consonants=bcdfghjklmnpqrtsvwxyz
for f in file*; do
printf "%s %d\n" "$f" "$(< "$f" tr A-Z a-z | tr -dc "$consonants" | wc -c)"
done
当然,尽管这完全是以 ASCII 为中心的(如果你有 GNU tr,它无论如何也不处理多字节字符。)