Wie zähle ich die Anzahl der Zeichen in einer Zeile mit Ausnahme eines bestimmten Zeichens?


9

Dies ist eine Teiledatei

N W N N N N N N N N N
N C N N N N N N N N N
N A N N N N N N N N N
N N N N N N N N N N N
N G N N N N N N N N N
N C N N N C N N N N N
N C C N N N N N N N N

In jeder Zeile möchte ich die Gesamtzahl aller Zeichen zählen, die nicht "N" sind.

meine Wunschausgabe

1
1
1
0
1
2
2

Verwenden Sie sed, um Dinge zu ersetzen, die Sie nicht interessieren, und awkum die verbleibende Länge zu zählensed 's/N//g ; s/\s//g' file | awk '{ print length($0); }'
Rolf

Antworten:


13

GNU awk Lösung:

awk -v FPAT='[^N[:space:]]' '{ print NF }' file
  • FPAT='[^N[:space:]]'- das Muster, das einen Feldwert definiert (jedes Zeichen außer Zeichen Nund Leerzeichen)

Die erwartete Ausgabe:

1
1
1
0
1
2
2


7

Angenommen, die Anzahl wird für jede andere Zeile als das Leerzeichen und benötigt N

$ perl -lne 'print tr/N //c' ip.txt 
1
1
1
0
1
2
2
  • Der Rückgabewert von trgibt an, wie viele Zeichen ersetzt wurden
  • c um den angegebenen Zeichensatz zu ergänzen
  • Beachten Sie die Verwendung der -lOption, entfernen Sie das Zeilenumbruchzeichen von der Eingabezeile, um Fehler nacheinander zu vermeiden, und fügen Sie das Zeilenumbruchzeichen für die Druckanweisung hinzu


Eine allgemeinere Lösung

perl -lane 'print scalar grep {$_ ne "N"} @F' ip.txt 
  • -aOption zum automatischen Teilen der Eingabezeile in Leerzeichen, die im @FArray gespeichert sind
  • grep {$_ ne "N"} @FGibt ein Array aller Elemente zurück, in @Fdenen die Zeichenfolge nicht übereinstimmtN
    • Regex-Äquivalent wäre grep {!/^N$/} @F
  • Die Verwendung von scalargibt die Anzahl der Elemente des Arrays an

6

Alternative awk Lösung:

awk '{ print gsub(/[^N[:space:]]/,"") }' file
  • gsub(...)- Die gsub()Funktion gibt die Anzahl der vorgenommenen Ersetzungen zurück.

Die Ausgabe:

1
1
1
0
1
2
2

6

Ein anderer awkAnsatz (gibt -1 für leere Zeilen zurück).

awk -F'[^N ]' '$0=NF-1""' infile

In komplexen Fällen wird -1 in leeren Zeilen und 0 in Leerzeichen (Tabulatoren / Leerzeichen) zurückgegeben.

awk -F'[^N \t]+' '$0=NF-1""' infile

wird -1für leere Zeilen gedruckt ... aber dann könnte es wünschenswert sein, eine Zeile, die nur aus N / Leerzeichen besteht, von einer leeren Zeile zu unterscheiden ...
Sundeep

1
@Sundeep Ja, das stimmt. siehe auch mein Update, wo Zeilen nur Tabulatoren oder Leerzeichen enthielten, um als 0
αғsнιη

5
  1. trund POSIX- Shell-Skript:

    tr -d 'N ' < file | while read x ; do echo ${#x} ; done
    
  2. bash, kshUnd zsh:

    while read x ; do x="${x//[ N]}" ; echo ${#x} ; done < file
    

1
kann verwendet werden awk '{print length()}', um die langsamere Shell-Schleife zu vermeiden .. aber dann könnte man alles mit awk selbst tun ...
Sundeep

@Sundeep, Es ist wahr, ( wenn beide zur gleichen Zeit gestartet werden), dass awkLooping ist schneller als Shell - Looping. Die Shell befindet sich jedoch immer im Speicher und ist awkmöglicherweise nicht - wenn sie awknoch nicht geladen oder ausgelagert ist - der Aufwand für das Laden ( die verlorene Zeit ) größer als der Vorteil des Laufens awk- insbesondere bei kleinen Schleife. In solchen Fällen ( dh in diesem Fall) awkkann es langsamer sein .
Agc


1
@Sundeep, ich mache mir Sorgen. Vor einiger Zeit habe ich floppy-basierte Linux-Distributionen verwendet , die von einer Diskette in ein paar Megabyte RAM laufen könnten. Die unnötige Verwendung awkin einem Shell-Skript könnte dazu führen, dass ein solches System auf allen Vieren crawlt. Im Allgemeinen gilt der gleiche Latenzwiderstand für Systeme mit eingeschränkter Firmware oder für Systeme unter hoher Last.
Agc

1

Eine kurze Kombination von tr und awk:

$ tr -d ' N' <file.in | awk '{ print length }'
1
1
1
0
1
2
2

Dadurch werden alle Leerzeichen und Ns aus der Eingabedatei gelöscht und awknur die Länge jeder Zeile gedruckt.


0

Eine andere einfache Möglichkeit besteht darin, dies in Python zu tun, das in den meisten Unix-Umgebungen vorinstalliert ist. Fügen Sie den folgenden Code in eine .py-Datei ein:

with open('geno') as f:
    for line in f:
        count = 0
        for word in line.split():
            if word != 'N':
                count += 1
        print(count)

Und dann mache:

python file.py

Von Ihrem Terminal. Was das Obige tut, ist:

  • für jede Zeile in einer Datei mit dem Namen "geno"
  • Setzen Sie einen Zähler auf 0 und erhöhen Sie ihn jedes Mal, wenn wir einen Wert finden! = 'N'
  • Wenn das Ende der aktuellen Zeile erreicht ist, drucken Sie den Zähler und fahren Sie mit der nächsten Zeile fort
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.