Unix - Anzahl der Spalten in der Datei

77

Gegeben eine Datei mit Daten wie diese (dh die Datei storage.dat)

sid|storeNo|latitude|longitude
2|1|-28.03720000|153.42921670
9|2|-33.85090000|151.03274200

Was wäre ein Befehl, um die Anzahl der Spaltennamen auszugeben?

dh im obigen Beispiel wäre es 4. (Anzahl der Pipe-Zeichen + 1 in der ersten Zeile)

Ich dachte so etwas wie:

awk '{ FS = "|" } ; { print NF}' stores.dat

Es werden jedoch alle Zeilen anstelle der ersten und für die erste Zeile 1 anstelle von 4 zurückgegeben

toop
quelle

Antworten:

117
awk -F'|' '{print NF; exit}' stores.dat 

Beenden Sie einfach gleich nach der ersten Zeile.

Matte
quelle
3
oderawk -F'|' 'NR==1{print NF}' stores.dat
Jaypal Singh
10
@ JaypalSingh: das liest die ganze Datei - keine Notwendigkeit dafür, besser früh aufhören.
Mat
Beide scheinen dieselbe korrekte Ausgabe zurückzugeben. Gibt es einen Leistungsvorteil von 1 gegenüber dem anderen (oder einen anderen Vorteil)?
Toop
2
@toop: Ja, siehe meinen vorherigen Kommentar. Meine Version liest nur einen Block aus der Datei, Jaypal liest die gesamte Datei.
Mat
1
@Mat Du bist genau richtig! @loop Mat ist absolut korrekt. exitist der richtige Weg, um es zu tun. Sie müssen nicht die gesamte Datei lesen, wenn Sie nur die Anzahl der Spalten wissen möchten. +1 :)
Jaypal Singh
37

Dies ist eine Problemumgehung (für mich: Ich benutze awk nicht sehr oft):

Zeigen Sie die erste Zeile der Datei mit den Daten an, ersetzen Sie alle Pipes durch Zeilenumbrüche und zählen Sie dann die Zeilen:

$ head -1 stores.dat | tr '|' '\n' | wc -l
miku
quelle
9
Für Dateien mit vielen Spalten (denken Sie an SNP-Daten) ist dies der richtige Weg. Mats Lösung ergab "awk: Programmlimit überschritten: maximale Anzahl von Feldern = 32767".
Die Unfun Cat
11

Sofern Sie dort keine Leerzeichen verwenden, sollten Sie diese in | wc -wder ersten Zeile verwenden können.

wcist "Word Count", das einfach die Wörter in der Eingabedatei zählt. Wenn Sie nur eine Zeile senden, wird die Anzahl der Spalten angezeigt.

Tom van der Woerdt
quelle
Ich habe versucht: head -1 store.dat | wc -w Aber das gibt nicht zurück, was ich will
toop
Das liegt daran, dass Sie das nicht durch |ein Leerzeichen ersetzen - es wcwerden Wörter gezählt, die durch Leerzeichen getrennt werden müssen. Verwenden Siehead -1 stores.dat | tr '|' ' ' | wc -w
Tom van der Woerdt
2
Bitte fügen Sie der Antwort der Vollständigkeit halber Ihren Kommentar hinzu.
Xofo
5

Du könntest es versuchen

Katze DATEI | awk '{print NF}'

Katze Kerr
quelle
2

Perl-Lösung ähnlich der awk-Lösung von Mat:

perl -F'\|' -lane 'print $#F+1; exit' stores.dat

Ich habe dies an einer Datei mit 1000000 Spalten getestet.


Wenn das Feldtrennzeichen ein Leerzeichen (ein oder mehrere Leerzeichen oder Tabulatoren) anstelle einer Pipe ist:

perl -lane 'print $#F+1; exit' stores.dat
Chris Koknat
quelle
1

Wenn Sie Python installiert haben, können Sie versuchen:

python -c 'import sys;f=open(sys.argv[1]);print len(f.readline().split("|"))' \
    stores.dat
Don Frage
quelle
In diesem speziellen Fall ist es kürzer, von der Standardeingabe zu lesencat x.txt | python -c "print raw_input().count('|') + 1"
Lie Ryan
kürzer ja, aber nicht schneller, wenn es viele lange Dateien gibt! Ich nahm an, dass er eine schnellere Lösung im Auge von reinen (sicher großen) Datendateien wollte.
Don Frage
1

Dies ist normalerweise das, was ich zum Zählen der Anzahl der Felder verwende:

head -n 1 file.name | awk -F'|' '{print NF; exit}'
user2533399
quelle
1

Wählen Sie eine beliebige Zeile in der Datei aus (im folgenden Beispiel ist es die 2. Zeile) und zählen Sie die Anzahl der Spalten, wobei das Trennzeichen ein Leerzeichen ist:

sed -n 2p text_file.dat | tr ' ' '\n' | wc -l
sAguinaga
quelle
0

Basierend auf der Antwort von Cat Kerr. Dieser Befehl arbeitet mit Solaris

awk '{print NF; exit}' stores.dat
Manu Mitra
quelle
Und dann sind Sie bei der akzeptierten Antwort ohne das richtige Feldtrennzeichen. Dies würde "1" für die Beispieleingabe zurückgeben.
Benjamin W.
Dies entspricht im Wesentlichen der akzeptierten Antwort ohne Feldtrennzeichen, da Bejamin sagt, dass 1 zurückgegeben wird, jedoch für durch Leerzeichen getrennte Dateien funktionieren sollte.
Discipulus
0

Sie können versuchen:

head -1 stores.dat | grep -o \|  | wc -l
user7231103
quelle
0

Richtig rein Weg

Unter Bash könnte man einfach:

IFS=\| read -ra headline <stores.dat
echo ${#headline[@]}
4

Viel schneller als ohne Gabeln und wiederverwendbar, wenn Sie $headlinedie volle Schlagzeile halten. Sie könnten zum Beispiel:

printf " - %s\n" "${headline[@]}"
 - sid
 - storeNo
 - latitude
 - longitude

Hinweis Diese Syntax steuert Leerzeichen und andere Zeichen in Spaltennamen korrekt.

Alternative: Starke binäre Überprüfung auf maximale Spalten in jeder Zeile

Was ist, wenn eine Zeile zusätzliche Spalten enthält?

Dieser Befehl sucht nach größeren Zeilen und zählt Trennzeichen :

tr -dc $'\n|' <stores.dat |wc -L
3

Es gibt maximal 3 Trennzeichen, dann 4 Felder.

F. Hauri
quelle