2011-12-25 37 views
32

Cho một tập tin với dữ liệu như thế này (tức là stores.dat tập tin)unix - đếm lần xuất hiện của nhân vật trên mỗi dòng/lĩnh vực

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

lệnh đó sẽ trả lại số lần xuất hiện của 't' là gì ký tự trên mỗi dòng?

ví dụ: sẽ trở lại:

count lineNum 
    4  1 
    3  2 
    6  3 

Ngoài ra, để làm điều đó bằng cách đếm lần xuất hiện bởi lĩnh vực này lệnh để trả lại kết quả sau đây là những gì?

ví dụ: đầu vào của cột 2 và ký tự 't'

count lineNum 
    1  1 
    0  2 
    1  3 

ví dụ: đầu vào của cột 3 và nhân vật 't'

count lineNum 
    2  1 
    1  2 
    4  3 
+0

hãy xem http://www.gnu.org/software/gawk/manual/gawk.html công cụ unix mạnh mẽ của nó – Chris

+0

http://unix.stackexchange.com/questions/18736/how-to -count-the-number-of-a-cụ thể-ký tự-trong-mỗi-dòng –

Trả lời

38

Để đếm kí tự trên mỗi dòng bạn có thể làm:

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

Để đếm xảy ra một nhân vật cho mỗi lĩnh vực/cột bạn có thể làm:

cột 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 

cột 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() giá trị trả về chức năng là số thay thực hiện. Vì vậy, chúng tôi sử dụng nó để in số.
  • NR giữ số dòng để chúng tôi sử dụng số đó để in số dòng.
  • Đối với sự cố in của trường cụ thể, chúng tôi tạo biến số fld và đặt số trường mà chúng tôi muốn trích xuất số lượng.
+0

tuyệt vời! cảm ơn vì đã gắn bó với nó - nó hoạt động. – toop

+0

Nó in "0" (lần xuất hiện) cũng có thể không được mong muốn ở đầu ra –

+0

@TarunSapra Nó thực sự được hiển thị như kết quả mong đợi trong câu hỏi. –

3

Một giải pháp có thể sử dụng perl:

Nội dung 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, $.; 
} 

Kịch bản chấp nhận ba thông số:

  1. Input tập tin
  2. Char để tìm kiếm
  3. Cột để tìm kiếm: Nếu cột là chữ số xấu, cột sẽ tìm kiếm tất cả các dòng.

Chạy kịch bản không có đối số:

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

Với lập luận và sản lượng của nó:

đây 0 là một cột xấu, nó tìm kiếm tất cả các dòng.

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

Ở đây nó tìm kiếm trong cột 1.

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

Ở đây nó tìm kiếm trong cột 3.

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

th không phải là một char.

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

wow, gotta tìm hiểu perl – toop

+0

Như thế này rất nhiều, nhưng chấp nhận câu trả lời khác để tích hợp dễ dàng hơn với bash – toop

0
cat stores.dat | awk 'BEGIN {FS = "|"}; {print $1}' | awk 'BEGIN {FS = "\t"}; {print NF}' 

đâu $1 sẽ là một số cột mà bạn muốn đếm.

2

Không cần awk hoặc perl, chỉ với bash và tiện ích Unix tiêu chuẩn:

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

Và đối với một cột cụ thể:

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

Và chúng tôi thậm chí có thể tránh 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 

và cắt sự kiện:

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 
31
grep -n -o "t" stores.dat | sort -n | uniq -c | cut -d : -f 1 

cho gần như chính xác kết quả bạn muốn:

4 1 
    3 2 
    6 3 

Nhờ @ Raghav-Bhushan cho grep -o gợi ý, những gì một lá cờ hữu ích. Cờ -n cũng bao gồm số dòng.

+1

Đây là một giải pháp thanh lịch và tổng quát hơn nhiều. –

+2

+1 vì không làm cho tôi gõ tất cả những điều đó awk – slf

+1

Tôi nghĩ rằng 'sort-n' có thể được phân phối với - không phải là đầu ra trong thứ tự số dòng anyway? –

1
$ 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 
0

Bạn cũng có thể tách dòng hoặc trường với "t" và kiểm tra độ dài của mảng kết quả - 1. Đặt biến col-0 đối với đường hoặc từ 1 đến 3 cho các cột:

awk -F'|' -v col=0 -v OFS=$'\t' 'BEGIN { 
    print "count", "lineNum" 
}{ 
    split($col, a, "t"); print length(a) - 1, NR 
} 
' stores.dat 
2
awk '{gsub("[^t]",""); print length($0),NR;}' stores.dat 

Cuộc gọi tới gsub() xóa mọi thứ trong dòng không có, sau đó chỉ in độ dài của những gì còn lại và số dòng hiện tại.

Bạn muốn làm điều đó chỉ cho cột 2?

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

Để đếm lần xuất hiện của một nhân vật trên mỗi dòng:

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

này đặt tách lĩnh vực với nhân vật mà cần phải được tính, sau đó sử dụng thực tế là số lĩnh vực là một trong những lớn hơn số phân cách.

Để đếm lần xuất hiện trong một cột cụ thể cut ra cột đầu tiên:

$ 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 
0
perl -e 'while(<>) { $count = tr/t//; print "$count ".++$x."\n"; }' stores.dat 

perl Một câu trả lời yay! Hàm tr/t // trả về số lần dịch đã xảy ra trên dòng đó, nói cách khác là số lần tr tìm thấy ký tự 't'. ++ $ x duy trì số lượng dòng.

Các vấn đề liên quan