it-swarm.com.de

Anzahl der Zeichen pro Zeile/Feld unter Unix

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
39
toop

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
  • Der Rückgabewert von 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. 
  • Für das Drucken von Vorkommen eines bestimmten Feldes erstellen wir eine Variable fld und geben die Feldnummer ein, aus der die Anzahl extrahiert werden soll. 
43
jaypal singh
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.

36
Gabriel Burt

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
12
artm

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:

  1. Eingabedatei
  2. Char zu suchen
  3. Zu durchsuchende Spalte: Wenn die Spalte eine ungültige Ziffer ist, wird die gesamte Zeile durchsucht.

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
3
Birei

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 cats 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
2
jfg956
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
2
vulcan
 $ 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
1
Haven Holmes
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. 

0
Steve Thorn

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
0
Cole Tierney
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.

0
Jelena