Linux 计算Unix上每行/每字段出现的字符数

Linux 计算Unix上每行/每字段出现的字符数,linux,bash,shell,unix,scripting,Linux,Bash,Shell,Unix,Scripting,给定一个包含如下数据的文件(即stores.dat文件) 返回每行“t”字符出现次数的命令是什么 他将返回: count lineNum 4 1 3 2 6 3 另外,要按字段计数,返回以下结果的命令是什么 例如,输入第2列和字符“t” count lineNum 1 1 0 2 1 3 count lineNum 2 1 1 2

给定一个包含如下数据的文件(即stores.dat文件)

返回每行“t”字符出现次数的命令是什么

他将返回:

count   lineNum
   4       1
   3       2
   6       3

另外,要按字段计数,返回以下结果的命令是什么

例如,输入第2列和字符“t”

count   lineNum
   1       1
   0       2
   1       3
count   lineNum
   2       1
   1       2
   4       3
例如,输入第3列和字符“t”

count   lineNum
   1       1
   0       2
   1       3
count   lineNum
   2       1
   1       2
   4       3

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

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

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

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
awk -F'|' -v fld=3 'BEGIN{print "count", "lineNum"}{print gsub(/t/,"",$fld) "\t" NR}' file
count lineNum
2       1
1       2
4       3
第3列:

awk -F'|' -v fld=2 'BEGIN{print "count", "lineNum"}{print gsub(/t/,"",$fld) "\t" NR}' file
count lineNum
1       1
0       2
1       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
    ,并放置我们希望从中提取计数的字段编号
      使用
      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, $.;
      }
      
      使用参数及其输出:

      这里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
      
      th
      不是字符

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

      其中,
      $1
      将是您要计算的列号。

      不需要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; }
      
      我们甚至可以避免
      tr
      cat
      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
      读取数据时;做
      new_data=${data//t/}
      计数=$(${数据}-${新数据}))
      测试$count-gt 0&&printf“%4d%5d\n”$count$num
      num=$($num+1))
      完成<文件
      
      和事件切割:

      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
      
      echo“count lineNum”
      num=1;OLF_IFS=$IFS;IFS=“|”
      读取时-数组_数据;做
      data=${array_data[1]}
      new_data=${data//t/}
      计数=$(${数据}-${新数据}))
      测试$count-gt 0&&printf“%4d%5d\n”$count$num
      num=$($num+1))
      完成<文件
      IFS=$OLF_IFS
      
      提供几乎完全符合您需要的输出:

        4 1
        3 2
        6 3
      

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

      您还可以使用“t”拆分行或字段,并检查结果数组-1的长度。将行的
      col
      变量设置为0,或将列的
      变量设置为1到3:

       $ cat -n test.txt
       1  test 1
       2  you want
       3  void
       4  you don't want
       5  ttttttttttt
       6  t t t t t t
      
       $ 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
      
      awk -F'|' -v col=0 -v OFS=$'\t' 'BEGIN {
          print "count", "lineNum"
      }{
          split($col, a, "t"); print length(a) - 1, NR
      }
      ' stores.dat
      
      对gsub()的调用删除行中所有不是t的内容,然后只打印剩余内容的长度和当前行号

      想只为第二栏做吗

      awk 'BEGIN{FS="|"} {gsub("[^t]","",$2); print NR,length($2);}' stores.dat
      

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

      $ 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-e'while(){$count=tr/t/;打印“$count”。++$x.“\n”}”stores.dat
      

      又是一个perl答案耶!tr/t//函数返回该行上发生翻译的次数,换句话说,tr找到字符“t”的次数+$x维护行号计数

      看一看,它是一个非常强大的unix工具,很多时候都是这样,但是接受另一个答案,更容易与Bash集成这是一个更加优雅和通用的解决方案。我认为可以省去
      sort-n
      ,输出不是按行号顺序吗?这很奇怪,确切的命令返回“10t”、“11”、“12”、“13”在我的Mac电脑上。@Gabrial Burt,你能在回答中解释一下每一步吗。。你的命令是什么,它们的修饰词如何影响正在发生的事情?如果你的Mac代码> GRP是奇怪的,考虑<代码> BREW安装< /代码>来获取和使用<代码> pCREGRIP。它打印“0”(发生)同样,这在未来可能并不理想output@TarunSapra它实际上显示为问题中的预期结果。请注意,
      gsub()
      将更改记录的内容。如果需要原始值,应在其他操作块之后调用
      gsub()
      (或将原始内容保存在变量中)。
      perl -e 'while(<>) { $count = tr/t//; print "$count ".++$x."\n"; }' stores.dat