linux-在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

此外,要按字段计数发生次数,返回以下结果的命令是什么?

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

count   lineNum
   1       1
   0       2
   1       3

例如。 输入第3列和字符“ t”

count   lineNum
   2       1
   1       2
   4       3
toop asked 2020-07-31T02:27:42Z
10个解决方案
46 votes

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

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
  • fld函数的返回值是替换的次数。 所以我们用它来打印数字。
  • fld保存行号,因此我们用它来打印行号。
  • 对于特定字段的打印事件,我们创建一个变量fld并放入我们要从中提取计数的字段编号。
jaypal singh answered 2020-07-31T02:28:19Z
41 votes
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标志也包括行号。

Gabriel Burt answered 2020-07-31T02:28:44Z
18 votes

要计算每行字符的出现次数:

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

这会将字段分隔符设置为需要计数的字符,然后使用以下事实:字段数比分隔符数大一。

要在特定的列cut中计算出现的次数,请先将该列排除在外:

$ 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
artm answered 2020-07-31T02:29:12Z
4 votes

使用th的一种可能的解决方案:

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. 要搜索的列:如果column是一个错误的数字,它将搜索所有行。

运行不带参数的脚本:

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

th不是字符。

perl script.pl stores.dat 'th' 3
Bad input
Birei answered 2020-07-31T02:30:20Z
4 votes

无需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; }

我们甚至可以避免使用trcats:

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
jfg956 answered 2020-07-31T02:30:53Z
3 votes
awk '{gsub("[^t]",""); print length($0),NR;}' stores.dat

调用gsub()会删除该行中所有非t的内容,然后仅打印剩余长度和当前行号。

是否只想为第2列做?

awk 'BEGIN{FS="|"} {gsub("[^t]","",$2); print NR,length($2);}' stores.dat
vulcan answered 2020-07-31T02:31:18Z
2 votes
 $ 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
Haven Holmes answered 2020-07-31T02:31:33Z
1 votes
cat stores.dat | awk 'BEGIN {FS = "|"}; {print $1}' |  awk 'BEGIN {FS = "\t"}; {print NF}'

其中$1是要计数的列号。

Jelena answered 2020-07-31T02:31:53Z
1 votes

您还可以使用“ t”分隔行或字段,并检查结果数组的长度-1。将2990119796836831945728变量设置为0,行设置为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
Cole Tierney answered 2020-07-31T02:32:13Z
1 votes
perl -e 'while(<>) { $count = tr/t//; print "$count ".++$x."\n"; }' stores.dat

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

Steve Thorn answered 2020-07-31T02:32:33Z
translate from https://stackoverflow.com:/questions/8629410/count-occurrences-of-character-per-line-field-on-unix