2017-10-24 2 views
1

Ich habe eine Datei wie folgt aus:Entfernen Reihen in bash basierend auf Werten

1 4014 1.97676 1 1 
1 4014 1.97676 2 1 
1 4014 1.97676 3 1 
1 2014 1.97676 4 1 
1 2014 1.97676 5 1 
1 401 1.97676 6 1 
1 401 1.97676 7 1 
1 401 1.97676 8 1 
1 14 1.97676 9 1 
1 14 1.97676 10 1 

Ich möchte diese Datei trimmen: Entfernen Sie Zeilen mit den Werten in der zweiten Spalte < 1000. Nach dem Trimmen sollte die Datei aussehen dies:

1 4014 1.97676 1 1 
1 4014 1.97676 2 1 
1 4014 1.97676 3 1 
1 2014 1.97676 4 1 
1 2014 1.97676 5 1 

Wie dies in bash zu erreichen? Ich möchte es nicht in Python machen, besonders in Pandas, weil sie langsam mit großen Dateien umgehen.

Eine andere Frage ist: Wie kann ich eine solche bash Befehle in einer .sh-Datei (ähnlich .py-Datei ausgeführt von Python) und führen Sie die Datei im Terminal wie folgt schreiben:

$bash clean_file.sh inputfile.txt > outputfile.txt 

Vielen Dank .



Hier ist, was ich tun möchte:

Die Datei ist wie folgt:

NODE_1_length_4014_cov_1.97676 1 1 
NODE_1_length_4014_cov_1.97676 2 1 
NODE_1_length_4014_cov_1.97676 3 1 
NODE_1_length_4014_cov_1.97676 4 1 
NODE_1_length_4014_cov_1.97676 5 1 
NODE_1_length_4014_cov_1.97676 6 1 
NODE_1_length_4014_cov_1.97676 7 1 
NODE_1_length_4014_cov_1.97676 8 1 
NODE_1_length_4014_cov_1.97676 9 1 
NODE_1_length_4014_cov_1.97676 10 1 

Ich mag würde reinigen es mit den folgenden Schritten:

#First, split the first column by the delimiter '_' and only keep the numbers: 
awk -F '_' -v OFS='\t' '{print $2,$4,$6,$7,$8}' 
#Second, remove the last two empty columns, because, after the first step, it generates two extra invisible columns, which need to be removed. 
cut -f 1-5 
#remove rows with values in the 2nd column less than 500 
awk '$2 >= 500 { print }' 

Ich habe 'Eingabedatei' und 'Ausgabedatei' nicht hinzugefügt n in den obigen Skripten, da jeder Schritt die Ausgabedatei des vorherigen Schritts als Eingabedatei verwendet. Ich weiß nicht, wie man die drei Schritte in einer Skriptdatei kombiniert und auf der Festplatte speichert. Ich möchte es im Terminal für Dateien ausführen, die an verschiedenen Orten auf meinem Computer gespeichert sind.

Vielen Dank!

+0

'entfernen Sie die letzten zwei leere columns' Sie diesen Schritt nicht brauchen ... die awk Lösung gewesen' awk -F sollte '_' -v OFS = '\ t' ‚{print $ 2, $ 4, $ 6} ' – Sundeep

+0

, um es mit neuer Anforderung zu kombinieren, verwenden Sie' awk-F '_' -v OFS = '\ t' '$ 2> = 500 {print $ 2, $ 4, $ 6}' auf Originaldatei .. nur ein einziger Befehl, keine Notwendigkeit, Skripte zu schreiben – Sundeep

+0

Das ist sehr hilfreich. Vielen Dank! –

Antwort

1

Bash ist das falsche Werkzeug.

awk '$2 >= 1000 { print }' 
+2

können Sie entfernen {{print} ' – karakfa

+0

Vielen Dank. Wie erstellt man dieses Skript in einer Datei und führt es im Terminal aus? Kann ich eine Reihe von "awk" - und "cut" -Befehlen in eine Datei einfügen und sie im Terminal ausführen, so dass sie für eine Reihe von Dateien denselben Job ausführt? –

+0

Dump es in eine Skriptdatei, geben Sie die Eingabe in Stdin, und die Ausgabe wird in stdout sein. –

1

Eine solche Filterung ist zwar trivial mit awk, sondern nur der Vollständigkeit halber (Bildung), hier ist eine bash -nur Version:

#!/bin/bash 

# "parse"/validate a script's argument (filename) 
if [[ ! -e "$1" ]]; then 
    echo "Usage: $0 FILE" 
    exit 
fi 

# iterate over lines, splitting into fields on whitespaces 
while read -ra fields; do 
    ((fields[1] >= 1000)) && echo "${fields[@]}" 
done <"$1" 

Die Nutzung ist wie:

$ ./clean_file.sh inputfile.txt > outputfile.txt 
0

Ihre Die zweite Beispieleingabedatei hat keine Testbedingung. So aktualisierte ich mit

$ sed -i '5,$s/4014/300/' file 

und es wurde

NODE_1_length_4014_cov_1.97676 1 1 
NODE_1_length_4014_cov_1.97676 2 1 
NODE_1_length_4014_cov_1.97676 3 1 
NODE_1_length_4014_cov_1.97676 4 1 
NODE_1_length_300_cov_1.97676 5 1 
NODE_1_length_300_cov_1.97676 6 1 
NODE_1_length_300_cov_1.97676 7 1 
NODE_1_length_300_cov_1.97676 8 1 
NODE_1_length_300_cov_1.97676 9 1 
NODE_1_length_300_cov_1.97676 10 1 

Sie die Einträge mit der Länge entfernen weniger als 500. Diese einfach awk Skript tun!

$ awk '{split($1,f1,"_")} f1[4]>=500' file 

NODE_1_length_4014_cov_1.97676 1 1 
NODE_1_length_4014_cov_1.97676 2 1 
NODE_1_length_4014_cov_1.97676 3 1 
NODE_1_length_4014_cov_1.97676 4 1 
Verwandte Themen