2017-08-25 5 views
1

hatte ich eine ähnliche Frage früher, aber dieses Mal muss ich etwas ein bisschen anspruchsvoller:Filtering mit awk basiert auf zwei Kriterien

In einer txt-Datei, die wie folgt aussieht:

147 186741 2S74M -162 
83 647172 1S75M -221 
163 584665 74M2S 271 
99 658416 5S65M6S -272 
163 718735 60M16S 243 

Ich möchte die awk, um die 3. Spalte zu betrachten, wenn sie das Zeichen "S" entweder auf der 2. oder 3. Position trifft, dann schaut sie auf die erste Spalte, wenn sie entweder "147" oder "83" trifft, verwirft sie diese Zeile. Der Rest der Ergebnisse wird an das zweite awk übergeben, wo es erneut auf die dritte Zeile schaut, wenn es am Ende auf das Zeichen "S" trifft, dann schaut es auf die erste Spalte und wenn es entweder "99" oder "163" findet Es verwirft diese Zeilen. Dann druckt es den Rest der Zeilen, die diese Filter nicht erfüllen.

habe ich versucht, etwas in dieser Richtung, bekam aber leere Datei:

awk -Ft '{if ($3 ~ /S$/ && $1 ~ /99|163/)} {next}' | awk -Ft '{if ($3 ~ /^..?S/ && $1 ~ /147|83/)} {next} $6 ~ /S/ {print}' input.txt > output.txt 
+0

Was bedeutet 'wenn es darauf stößt '? Wenn $ 1 genau "123147456" ist, dann wurde '147' gefunden" oder nicht? Bitte verwenden Sie Begriffe wie "ist genau" oder "enthält" (zusammen mit Teilübereinstimmung und genauer Übereinstimmung und Zeichenfolge oder numerischer oder Regexp-Vergleich) und zeigen Beispiele, die Ihren Kriterien nicht entsprechen, insbesondere Regentag/Randfälle. Warum setzen Sie '-Ft' auch, wenn in Ihrer Eingabedatei keine' '' '' '' '' '' '' '' '' '' '' 'vorhanden sind und das Skript dann WIRKLICH bricht? Schließlich - Ihre erste Awk-Anweisung als kein Bein, wo es eine Ausgabe druckt, noch liest es eine Eingabedatei, also erhalten Sie natürlich eine leere Ausgabedatei. –

Antwort

0

Da Sie Input_file nicht angezeigt haben, welches y ou benutzen, also habe ich mein Beispiel genommen, das auf deiner gezeigten Input_file basiert, sagen wir folgendes ist deine Input_file.

cat Input_file 
147 186741 2S74M -162 
83 647172 1S75M -221 
163 584665 74M2S 271 
99 658416 5S65M6S -272 
163 718735 60M16S 243 
147 186741 2K74M -162 
83 647172 1K75M -221 
163 584665 74M2K 271 
99 658416 5S65M6K -272 
163 718735 60M16S 243 

nun folgende ist mein Code:

awk '(($1==147 || $1==83) && (substr($3,2,1)=="S" || substr($3,3,1)=="S")) || (substr($3,length($3))=="S" && ($1==99 || $1==163)){next} 1' Input_file 

Wenn ich jetzt über awk laufen erhalte ich diese Werte (die ich einfach hinzugefügt haben, zu überprüfen, ob mein Code funktioniert oder nicht) wie folgt.

awk '(($1==147 || $1==83) && (substr($3,2,1)=="S" || substr($3,3,1)=="S")) || (substr($3,length($3))=="S" && ($1==99 || $1==163)){next} 1' Input_file 
147 186741 2K74M -162 
83 647172 1K75M -221 
163 584665 74M2K 271 
99 658416 5S65M6K -272 

So könnte man alle diese Linien sehen, die unter nicht von Ihnen zur Verfügung gestellten Bedingungen kommen, werden immer gedruckt, geben irgendwann mir Erklärung hinzufügen, werden auch hier.

EDIT: Hinzufügen von Erklärung der oben genannten Code auch hier, bitte nicht laufen, wie ich es in verschiedene Abschnitte für OP Verständnis nur geteilt habe.

awk '(($1==147 || $1==83)\ ##First condition which re-presents your first awk starts here. checking conditions where $1 value is either 147 OR $1 value is 83 
&& \      ## AND 
(substr($3,2,1)=="S" \  ##substring of 3rd column is EQUAL to letter S 
|| \      ## OR 
substr($3,3,1)=="S"))\  ##substring of 3rd column is EQUAL to letter S 
|| \      ##OR(means either that first aw condition should be TRUE or this following one), the second major condition for which you used second awk I clubbed both the awks into 2 major conditions here. 
(substr($3,length($3))=="S"\##checking if substring of column 3s last letter is EQUAL to S here. 
&& \      ## AND 
($1==99 || $1==163)){  ##$1 value is either 99 or 163. So if either of above 2 major conditions are TRUE then perform following statements. 
next      ##next, it is awk keyword which will skip all further statements of line now, without doing any action. 
} 
1       ##awk works on method of condition and then action, so here I am making condition as TRUE by mentioning as 1 and NO action is mentioned so be default print action will happen which will print current line. 
' Input_file     ##mentioning Input_file here. 
+1

Dies funktioniert genauso gut wie die vorherige Lösung (ich muss noch einen zusätzlichen Filterschritt machen, den ich vergessen habe zu erwähnen, aber es sollte funktionieren). Ich mag die Art, wie du "substr" benutzt hast und danke für die zusätzliche Erklärung, da ich gerade viel von deinem Beitrag gelernt habe (als Anfänger in der Programmierung, es hilft wirklich, diese zu haben)! Vielen Dank, ich schätze es sehr. – ThePresident

+0

Froh, dass es Ihnen geholfen hat, können Sie diesen Link einmal verweisen, https://stackoverflow.com/help/someone-answers. Teilen Sie weiter und lernen Sie weiter. – RavinderSingh13

0

Für den Anfang, die 6 $ ist möglicherweise ein Tippfehler.

Jetzt versuchen wir es in Schritten. Schritt 1:

awk '$1 ~ /147|83/ && $3 ~ /^..?S/ {next;} {print;}' test.txt 

lässt uns mit:

163 584665 74M2S 271 
99 658416 5S65M6S -272 
163 718735 60M16S 243 

Wenn Sie diese Zeilen in einer Datei test2.txt setzen, dann Anwendung:

awk '($1 ~ /99|163/ && $3 ~ /S$/) {next;} {print;}' test2.txt 

lässt uns keine gültigen Linien, weil alle 3. Spalten ein 'S' am Ende haben und mit entweder 99 oder 163 beginnen.

+0

... und Sie könnten beide Anweisungen auf einmal machen. Wie awk '($ 1 ~/147 | 83/&& $ 3 ~/^ ..?S /) || ($ 1 ~/99 | 163/&& $ 3 ~/S $ /) {next;} {print;} 'test.txt –

+0

Ja, beides funktioniert gut und ich bevorzuge die Ein-Zeilen-Anweisung. Ich werde es ein wenig modifizieren müssen, da ich vergessen habe, ein drittes Kriterium zu erwähnen, bei dem ich alle Lesevorgänge entfernen werde, die kein "S" haben, aber ich denke, dass ich das herausfinden kann. Vielen Dank!!! – ThePresident

+0

NP. Lassen Sie uns wissen, wenn Sie stecken bleiben. –

Verwandte Themen