unix – 统计每行/字段出现的字符数

给定一个像这样的数据文件(即stores.dat文件)

sid|storeNo|latitude|longitude 2tt|1|-28.0372000t0|153.42921670 9|2t|-33tt.85t09t0000|15t1.03274200 

什么命令会返回每行't'字符的出现次数?

例如。 会返回:

 count lineNum 4 1 3 2 6 3 

另外,要按字段的出现次数来做,返回以下结果的命令是什么?

例如。 input第2列和字符“t”

 count lineNum 1 1 0 2 1 3 

例如。 第3栏input字符't'

 count lineNum 2 1 1 2 4 3 

Solutions Collecting From Web of "unix – 统计每行/字段出现的字符数"

要计算每行字符的出现次数,您可以:

 awk -F'|' 'BEGIN{print "count", "lineNum"}{print gsub(/t/,"") "\t" NR}' file count lineNum 4 1 3 2 6 3 

要计算每个字段/列的字符出现次数,您可以执行以下操作:

第2栏:

 awk -F'|' -v fld=2 'BEGIN{print "count", "lineNum"}{print gsub(/t/,"",$fld) "\t" NR}' file count lineNum 1 1 0 2 1 3 

第3栏:

 awk -F'|' -v fld=3 'BEGIN{print "count", "lineNum"}{print gsub(/t/,"",$fld) "\t" NR}' file count lineNum 2 1 1 2 4 3 
  • gsub()函数的返回值是进行的替换次数。 所以我们用它来打印这个号码。
  • NR保存行号,所以我们用它来打印行号。
  • 为了打印特定字段的出现,我们创建一个变量fld并把我们希望从中提取计数的字段号。
 grep -n -o "t" stores.dat | sort -n | uniq -c | cut -d : -f 1 

几乎精确地输出你想要的输出:

  4 1 3 2 6 3 

感谢@ raghav-bhushan的grep -o提示,多么有用的标志。 -n标志也包括行号。

要计算每行字符的出现次数,请执行以下操作:

 $ awk -F 't' '{print NF-1, NR}' input.txt 4 1 3 2 6 3 

这将字段分隔符设置为需要计数的字符,然后使用字段数大于分隔符数的事实。

要计算特定列中的出现次数,首先要删除该列:

 $ cut -d '|' -f 2 input.txt | awk -F 't' '{print NF-1, NR}' 1 1 0 2 1 3 $ cut -d '|' -f 3 input.txt | awk -F 't' '{print NF-1, NR}' 2 1 1 2 4 3 

一个可能的解决方案使用perl

script.pl的内容:

 use warnings; use strict; ## Check arguments: ## 1.- Input file ## 2.- Char to search. ## 3.- (Optional) field to search. If blank, zero or bigger than number ## of columns, default to search char in all the line. (@ARGV == 2 || @ARGV == 3) or die qq(Usage: perl $0 input-file char [column]\n); my ($char,$column); ## Get values or arguments. if ( @ARGV == 3 ) { ($char, $column) = splice @ARGV, -2; } else { $char = pop @ARGV; $column = 0; } ## Check that $char must be a non-white space character and $column ## only accept numbers. die qq[Bad input\n] if $char !~ m/^\S$/ or $column !~ m/^\d+$/; print qq[count\tlineNum\n]; while ( <> ) { ## Remove last '\n' chomp; ## Get fields. my @f = split /\|/; ## If column is a valid one, select it to the search. if ( $column > 0 and $column <= scalar @f ) { $_ = $f[ $column - 1]; } ## Count. my $count = eval qq[tr/$char/$char/]; ## Print result. printf qq[%d\t%d\n], $count, $.; } 

该脚本接受三个参数:

  1. 输入文件
  2. 字符搜索
  3. 要搜索的列:如果列是坏数字,则搜索所有行。

不带参数运行脚本:

 perl script.pl Usage: perl script.pl input-file char [column] 

有了参数和输出:

这里0是一个坏列,它搜索所有的行。

 perl script.pl stores.dat 't' 0 count lineNum 4 1 3 2 6 3 

在这里它在第1列进行搜索。

 perl script.pl stores.dat 't' 1 count lineNum 0 1 2 2 0 3 

在这里它在第3列进行搜索。

 perl script.pl stores.dat 't' 3 count lineNum 2 1 1 2 4 3 

这不是一个字符。

 perl script.pl stores.dat 'th' 3 Bad input 

不需要awk或perl,只需要bash和标准的Unix工具:

 cat file | tr -c -d "t\n" | cat -n | { echo "count lineNum" while read num data; do test ${#data} -gt 0 && printf "%4d %5d\n" ${#data} $num done; } 

对于一个特定的列:

 cut -d "|" -f 2 file | tr -c -d "t\n" | cat -n | { echo -e "count lineNum" while read num data; do test ${#data} -gt 0 && printf "%4d %5d\n" ${#data} $num done; } 

我们甚至可以避免trcat s:

 echo "count lineNum" num=1 while read data; do new_data=${data//t/} count=$((${#data}-${#new_data})) test $count -gt 0 && printf "%4d %5d\n" $count $num num=$(($num+1)) done < file 

和事件切割:

 echo "count lineNum" num=1; OLF_IFS=$IFS; IFS="|" while read -a array_data; do data=${array_data[1]} new_data=${data//t/} count=$((${#data}-${#new_data})) test $count -gt 0 && printf "%4d %5d\n" $count $num num=$(($num+1)) done < file IFS=$OLF_IFS 
 awk '{gsub("[^t]",""); print length($0),NR;}' stores.dat 

对gsub()的调用将删除不在的行中的所有内容,然后仅显示剩余内容的长度和当前行号。

想只为第2列做?

 awk 'BEGIN{FS="|"} {gsub("[^t]","",$2); print NR,length($2);}' stores.dat 
  $ cat -n test.txt 1 test 1 2 you want 3 void 4 you don't want 5 ttttttttttt 6 tttttt $ awk '{n=split($0,c,"t")-1;if (n!=0) print n,NR}' test.txt 2 1 1 2 2 4 11 5 6 6 
 cat stores.dat | awk 'BEGIN {FS = "|"}; {print $1}' | awk 'BEGIN {FS = "\t"}; {print NF}' 

$1就是你想要计算的列号。

您也可以用“t”分隔行或字段,并检查结果数组的长度 – 1.对于行设置col变量为0,对于列设置col变量为1到3:

 awk -F'|' -v col=0 -v OFS=$'\t' 'BEGIN { print "count", "lineNum" }{ split($col, a, "t"); print length(a) - 1, NR } ' stores.dat 
 perl -e 'while(<>) { $count = tr/t//; print "$count ".++$x."\n"; }' stores.dat 

另一个Perl回答耶! tr / t //函数返回在该行上发生翻译的次数,换句话说, tr发现字符“ t ”的次数。 ++ $ x维护行号计数。