Gegeben eine Datei mit solchen Daten (zB die Datei stores.dat)
sid|storeNo|latitude|longitude
2tt|1|-28.0372000t0|153.42921670
9|2t|-33tt.85t09t0000|15t1.03274200
Was ist der Befehl, der die Anzahl der Vorkommen des 't'-Zeichens pro Zeile zurückgeben würde?
z.B. würden zurückkehren:
count lineNum
4 1
3 2
6 3
Um dies durch die Anzahl der Vorkommen nach Feld zu tun, wie lautet der Befehl, um die folgenden Ergebnisse zurückzugeben?
z.B. Eingabe von Spalte 2 und Zeichen 't'
count lineNum
1 1
0 2
1 3
z.B. Eingabe von Spalte 3 und Zeichen 't'
count lineNum
2 1
1 2
4 3
Um das Vorkommen eines Zeichens pro Zeile zu zählen, können Sie Folgendes tun:
awk -F'|' 'BEGIN{print "count", "lineNum"}{print gsub(/t/,"") "\t" NR}' file
count lineNum
4 1
3 2
6 3
Um das Vorkommen eines Zeichens pro Feld/Spalte zu zählen, können Sie Folgendes tun:
Spalte 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
Spalte 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()
ist die Anzahl der vorgenommenen Ersetzungen. Also benutzen wir das, um die Nummer auszudrucken. NR
enthält die Zeilennummer, so dass wir sie zum Drucken der Zeilennummer verwenden. fld
und geben die Feldnummer ein, aus der die Anzahl extrahiert werden soll. grep -n -o "t" stores.dat | sort -n | uniq -c | cut -d : -f 1
gibt fast genau die gewünschte Ausgabe:
4 1
3 2
6 3
Vielen Dank an @ raghav-bhushan für den grep -o
-Hinweis, was für eine nützliche Flagge. Das Flag -n enthält auch die Zeilennummer.
Zu zählen Vorkommen eines Zeichens pro Zeile:
$ awk -F 't' '{print NF-1, NR}' input.txt
4 1
3 2
6 3
dadurch wird das Feldtrennzeichen auf das Zeichen gesetzt, das gezählt werden muss, und die Tatsache, dass die Anzahl der Felder um eins größer ist als die Anzahl der Trennzeichen.
Um Vorkommen in einer bestimmten Spalte zu zählen, cut
zuerst aus dieser Spalte heraus:
$ 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
Eine mögliche Lösung mit Perl
:
Inhalt von 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, $.;
}
Das Skript akzeptiert drei Parameter:
Das Skript ohne Argumente ausführen:
Perl script.pl
Usage: Perl script.pl input-file char [column]
Mit Argumenten und deren Ausgabe:
Hier ist 0 eine fehlerhafte Spalte, die alle Zeilen durchsucht.
Perl script.pl stores.dat 't' 0
count lineNum
4 1
3 2
6 3
Hier wird in Spalte 1 gesucht.
Perl script.pl stores.dat 't' 1
count lineNum
0 1
2 2
0 3
Hier wird in Spalte 3 gesucht.
Perl script.pl stores.dat 't' 3
count lineNum
2 1
1 2
4 3
th
ist kein Zeichen.
Perl script.pl stores.dat 'th' 3
Bad input
Keine Notwendigkeit für awk oder Perl, nur mit bash und Standard-Unix-Dienstprogrammen:
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; }
Und für eine bestimmte Kolumne:
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; }
Und wir können sogar tr
und die cat
s vermeiden:
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
und event the cut:
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
Der Aufruf von gsub () löscht alles in der Zeile, die nicht t ist, und druckt dann nur die Länge des verbleibenden Restes und die aktuelle Zeilennummer.
Möchten Sie es nur für Spalte 2 tun?
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 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
Perl -e 'while(<>) { $count = tr/t//; print "$count ".++$x."\n"; }' stores.dat
Eine weitere Antwort von Perl! Die Funktion tr/t // gibt die Anzahl der Male zurück, mit denen die Übersetzung in dieser Zeile stattfand, mit anderen Worten, wie oft tr das Zeichen ' t ' gefunden hat. ++ $ x behält die Anzahl der Zeilennummern bei.
Sie können die Zeile oder das Feld auch mit "t" teilen und die Länge des resultierenden Arrays überprüfen. 1. Setzen Sie die Variable col
für die Zeile auf 0 oder für Spalten auf 1 bis 3:
awk -F'|' -v col=0 -v OFS=$'\t' 'BEGIN {
print "count", "lineNum"
}{
split($col, a, "t"); print length(a) - 1, NR
}
' stores.dat
cat stores.dat | awk 'BEGIN {FS = "|"}; {print $1}' | awk 'BEGIN {FS = "\t"}; {print NF}'
Dabei wäre $1
eine Spaltennummer, die Sie zählen möchten.