2016-06-28 12 views
1

Ich habe eine Tab-getrennte Datei und möchte ein paar Spalten mit extrahieren.Bash: extrahieren Spalten mit Schnitt und Filter eine Spalte weiter

Zwei Beispielzeile

(...) 
0 0 1 0 AB=1,2,3;CD=4,5,6;EF=7,8,9 0 0 
1 1 0 0 AB=2,1,3;CD=1,1,2;EF=5,3,4 0 1 
(...) 

Was will ich erreichen Spalten 2,3,5 und 7 wählen, jedoch aus Spalte 5 nur CD=4,5,6.

So ist mein erwartetes Ergebnis

0 1 CD=4,5,6; 0 
1 0 CD=1,1,2; 1 

Wie kann ich für dieses Problem Ausschneiden und grep auf einem der extrahierten Spalten laufen? Jeder andere One-Liner ist natürlich auch in Ordnung.

+0

Hat es zu mit 'cut' gemacht werden? 'awk' wäre dafür viel besser, da Sie die' split() 'Funktion für diese Spalte verwenden können, um einen Teil davon zu extrahieren. – Barmar

+0

Er sagte, jeder andere One-Liner ist auch in Ordnung, so dass Sie wahrscheinlich gehen können und geben Sie ihm Ihre "awk" Antwort – Andrew

+0

'awk' ist auch völlig in Ordnung, ich dachte gerade geschnitten als erste. – maxie

Antwort

4

hier ist ein weiterer awk

$ awk -F'\t|;' -v OFS='\t' '{print $2,$3,$6,$NF}' file 

0  1  CD=4,5,6  0 
1  0  CD=1,1,2  1 

oder mit Ausschneiden/Einfügen

$ paste <(cut -f2,3 file) <(cut -d';' -f2 file) <(cut -f7 file) 

0  1  CD=4,5,6  0 
1  0  CD=1,1,2  1 
+0

Meine Lieblingslösung ist mit 'cut' und' paste'. – maxie

3

Einfacher getan mit awk. Teilen Sie das fünfte Feld unter Verwendung von ; als Trennzeichen, und drucken Sie dann das zweite Teilfeld.

awk 'BEGIN {FS="\t"; OFS="\t"} 
    {split($5, a, ";"); print $2, $3, a[2]";", $7 }' inputfile > outputfile 

Wenn Sie drucken möchten, je nachdem, welche Teilfeld mit CD= beginnt, verwenden Sie eine Schleife:

awk 'BEGIN {FS="\t"; OFS="\t"} 
    {n = split($5, a, ";"); 
     for (i = 1; i <= n; i++) { 
     if (a[i] ~ /^CD=/) subfield = a[i]; 
     } 
     print $2, $3, subfield";", $7}' <inputfile> outputfile 
+0

Was würde ich ändern, wenn die Anzahl der Einträge im 5. Feld nicht immer gleich ist (und nicht immer 'CD = ...' enthält)? – maxie

+1

Sie wollen also drucken, welcher Eintrag im 5. Feld mit 'CD =' beginnt, nicht immer der 2. Eintrag? Das war aus der Frage nicht offensichtlich, da das Ergebnis mit der Beispiel-Eingabedatei identisch ist. – Barmar

+0

Das stimmt, danke, dass du das aufzeigst, das war mir zu Beginn nicht klar. – maxie

1

Ich denke, awk ist das beste Werkzeug für diese Art von Aufgabe und die anderen beiden Antworten geben Ihnen gute kurze Lösungen.

Ich möchte darauf hinweisen, dass Sie awk's integrierte Splitting-Funktion verwenden können, um mehr Flexibilität beim Parsen der Eingabe zu erhalten. Hier ist ein Beispiel-Skript, das implizite Spaltung verwendet:

parse.awk

# Remember second, third and seventh columns 
{ 
    a = $2 
    b = $3 
    d = $7 
} 

# Split the fifth column on ";". After this the positional variables 
# (e.g. $1, # $2, ..., $NF) contain the fields from the previous 
# fifth column 
{ 
    oldFS = FS 
    FS = ";" 
    $0 = $5 
} 

# For example to test if the second elemnt starts with "CD", do 
# something like this 
$2 ~ /^CD/ { 
    c = $2 
} 

# Print the selected elements 
{ 
    print a, b, c, d 
} 

# Restore FS 
{ 
    FS = oldFS 
} 

Run es wie folgt aus:

awk -f parse.awk FS='\t' OFS='\t' infile 

Ausgang:

0 1 CD=4,5,6 0 
1 0 CD=1,1,2 1 
Verwandte Themen