2017-07-20 2 views
1

Wenn ich eine Registerkarte delimeted Datendatei input.dat mit einem Format wie:Wie verarbeiten Sie mehrere Felder, die durch eine Pipe laufen?

#id acct name city   age 
12 100290 Sally San Francisco 24 
15 102911 Jerry Sacramento 40 
99 102134 Amir Eureka  82 

Kann ich cut(1) oder etwas ähnliches mehr Verarbeitungsfunktionen ex :(lookup_id, scrub_acct, scrub_name, lookup_city, scrub_age) pro Feld wie die Datenläufe laufen durch eine Pfeife?

Es ist einfach, dies mit einem Feld zu tun:

cat input.dat | cut -f1 | lookup_id > output.dat

aber ich frage mich, ob es eine Möglichkeit gibt, dies pro Feld zu tun, und haben die zu OUTPUT.DAT umgeleitet Ergebnisse.

#id acct name city   age 
AA XXXXX0 SXXXX city-57  20s 
AC XXXXX1 JXXXX city-29  40s 
AF XXXXX4 AXXXX city-100  80s 

Vielleicht eine vorge Frage ist, kann man (tun dies einfach)?

Ich überlege auch, wie paste(1) eine Alternative sein könnte, nur die Spalten wieder zusammenkleben, aber vielleicht gibt es einen besseren Weg.

+1

Ich schlage vor, "awk" zu betrachten. – Cyrus

+0

ah guter Punkt, ich denke, Sie könnten eine Funktion auf jedem Feld ausführen und eine Subshell starten. Gibt es keinen Weg, dies mit Schnitt zu tun? Awk ist manchmal so ein Biest. @Cyrus – qodeninja

+0

Also 'Lookup_id, scrub_acct, scruelf_name, lookup_city, scrub_age' sind Shell-Funktionen? – anubhava

Antwort

2

Normalerweise ist es einfacher, Zeile, Spalte Daten in awk zu verarbeiten, aber wegen Beteiligung von Shell-Funktionen ist es besser, diese selbst in der Schale zu handhaben.

Unter der Annahme, lookup_id, scrub_acct, scrub_name, lookup_city, scrub_age sind Shell-Funktionen oder Skripte, die Eingabe lesen von stdin Sie eine Reihe von ihnen erstellen können sie und rufen, während sie durch jeden Datensatz aus Eingabedatei Looping:

# example shell functions 
lookup_id() { read str; printf "lookup_id: %s\n" "$str"; } 
scrub_acct() { read str; printf "scrub_acct: %s\n" "$str"; } 
scrub_name() { read str; printf "scrub_name: %s\n" "$str"; } 
lookup_city() { read str; printf "lookup_city: %s\n" "$str"; } 
scrub_age() { read str; printf "scrub_age: %s\n" "$str"; }  

# array of functions or scripts to be invoked 
fnarr=(lookup_id scrub_acct scrub_name lookup_city scrub_age) 

# main processing 
while IFS=$'\t' read -ra ary; do 
    for ((i=0; i<${#ary[@]}; i++)); do 
     # call function for each field value 
     "${fnarr[i]}" <<< "${ary[i]}" 
    done 
    echo '=============================' 
done < <(tail -n +2 file) 

Ausgang:

lookup_id: 12 
scrub_acct: 100290 
scrub_name: Sally 
lookup_city: San Francisco 
scrub_age: 24 
============================= 
lookup_id: 15 
scrub_acct: 102911 
scrub_name: Jerry 
lookup_city: Sacramento 
scrub_age: 40 
============================= 
lookup_id: 99 
scrub_acct: 102134 
scrub_name: Amir 
lookup_city: Eureka 
scrub_age: 82 
============================= 
+1

variable Substitution, sehr schlau. Sie verwenden das als eine Art Dispatcher, danke für die Idee! – qodeninja

+1

'" $ {fnarr [i]} "<<<" $ {ary [i]} ", um effizienter zu sein? – codeforester

+0

Ja das ist richtig, es vermeidet eine Subshell (bearbeitet) – anubhava

1

Probieren Sie etwas wie dies mit awk:

awk -F'\t' '{system("lookup_id " $1); printf("\t"); \ 
      system("scrub_acct " $2); printf("\t"); \ 
      ... 
      }' input.dat 
Verwandte Themen