Ich habe eine Datei, die so aussieht und 2 Spalten hat (durch Leerzeichen getrennt):
chr1.21.imputed_info:1 100880328
chr1.31.imputed_info:1 10566215
chr1.23.imputed_info:--- 110198129
chr1.23.imputed_info:--- 114445880
chr1.24.imputed_info:--- 118141492
chr1.25.imputed_info:--- 120257110
chr1.25.imputed_info:1 121280613
chr1.30.imputed_info:--- 121287994
chr1.30.imputed_info:--- 145604302
Ich möchte die Zahl nach "chr" aus 1-22 und der zweiten Spalte extrahieren. Meine Ausgabe würde also so aussehen:
1 100880328
1 10566215
1 110198129
1 114445880
1 118141492
1 120257110
1 121280613
1 121287994
1 145604302
Einige wichtige Überlegungen:
- Wie gesagt, die Zahl direkt nach "chr" geht von 1-22, also könnte es chr1, chr2 ... chr22 sein.
Die Zahl nach chr1, chr2 usw. kann bis zu 50 betragen. Sie können also beispielsweise chr1.50 oder chr2.45 usw. Haben
Der Teil "info:" am Ende der Spalte1 sieht möglicherweise wie folgt aus: info: 1, info: 2 .. info: 22 ODER info: ---
Ich habe mir das in Bash ausgedacht:
cat file.txt | sed 's/chr//g' | sed 's/.imputed_info://g'
Das bringt mich sehr nahe, aber es macht das:
1.211 100880328
1.31 10566215
1.23--- 110198129
1.23--- 114445880
1.24--- 118141492
1.25--- 120257110
1.251 121280613
1.25--- 121287994
1.30--- 145604302
1.301 149906413
Ich weiß, dass es Möglichkeiten gibt, dies in R und Python zu tun, aber ich sollte sagen, dass dies eine riesige Datei ist, so dass das Durchlaufen von Bash eine große Zeitersparnis wäre. Wenn also jemand eine nette (und idealerweise saubere Lösung hat - ich erkenne meine Sed Befehl ist irgendwie hässlich) es wäre toll. Vielen Dank.
5 Antworten
Kürzere Art:
sed 's/^chr//;s/\..* / /' filename
BEARBEITEN:
Übersetzung: Entfernen Sie das führende "chr" (falls vorhanden) und ersetzen Sie alles vom ersten "." bis zum letzten Leerzeichen (dh einem '.', gefolgt von irgendetwas, gefolgt von '') mit einem einzelnen Leerzeichen.
Ich würde awk
verwenden:
awk -F'[. ]' '{print substr($1,4), $NF}' file.txt
Dadurch wird jede Zeile nach Punkt oder Leerzeichen aufgeteilt und das erste Feld beginnend mit dem 4. Zeichen und dem letzten Feld gedruckt. (NF
ist die Anzahl der Felder, $NF
ist das letzte Feld)
Ausgabe:
1 100880328
1 10566215
1 110198129
1 114445880
1 118141492
1 120257110
1 121280613
1 121287994
1 145604302
sed 's/chr\([0-9]*\)[^ ]*[ ]*\([0-9]*\)/\1\t\2/' file.txt
Angenommen, Sie haben mit erweitertem Regex sediert:
sed -r -n 's/chr(2[0-2]|1?[0-9])\..+\s([0-9]+)/\1 \2/p' file.txt
Wenn die Zahl nach chr
nicht höher als 22 sein darf, können Sie den Ausdruck auf vereinfachen (ohne erweiterten regulären Ausdruck)
sed -r 's/chr([0-9]+)\..+\s([0-9]+)/\1 \2/' file.txt
Regex erklärt
chr
- Literal-Übereinstimmung(2[0-2]|1?[0-9])
- erste übereinstimmende Gruppe-
2[0-2]
- 20 bis 22 -
|
oder (wenn es nicht 20-22 ist, testen Sie den nächsten Ausdruck in der Gruppe) -
1?
- null oder eins1
-
[0-9]
- 0-9
-
\.
- Literalpunkt.+\s
- ein oder mehrere Zeichen, gefolgt von einem Leerzeichen([0-9]+)
- zweite übereinstimmende Gruppe, die mit einer oder mehreren Ziffern übereinstimmt/\1 \2/
- durch erste und zweite übereinstimmende Gruppe ersetzen
Ergebnis
Ich habe Ihr Beispiel erweitert auf
chr1.21.imputed_info:1 100880328
chr2.31.imputed_info:1 10566215
chr11.23.imputed_info:--- 110198129
chr12.23.imputed_info:--- 114445880
chr22.24.imputed_info:--- 118141492
chr1.25.imputed_info:--- 120257110
chr1.25.imputed_info:1 121280613
chr1.30.imputed_info:--- 121287994
chr1.30.imputed_info:--- 145604302
Die Ausgabe von sed
lautet:
1 100880328
2 10566215
11 110198129
12 114445880
22 118141492
1 120257110
1 121280613
1 121287994
1 145604302
Kurzer Weg:
sed 's/chr\([^.]*\).* /\1 /' file
Verwenden von sed
unter allen angewendeten Bedingungen:
sed 's/^chr\(1[1-9]\{0,1\}\|10\|2[012]\)\.\(1[1-9]\{0,1\}\|10\|[234][0-9]\|50\)[^ ]* *\([^ ]*\)/\1 \3/' file
Verwenden Sie sed
nur mit der folgenden Syntax:
sed 's/^chr\([1-9][1-9]*\)\.[1-9][1-9]*[^ ]* *\([^ ]*\)/\1 \2/' file
Verwenden von awk
:
awk '
/^chr([0-9]+)\.[0-9]+/{
match($1, /[0-9]+/);
$1 = substr($1, RSTART, RLENGTH);
print;
}' file
Ausgabe:
1 100880328
1 10566215
1 110198129
1 114445880
1 118141492
1 120257110
1 121280613
1 121287994
1 145604302
Neue Fragen
bash
Bei Fragen zu Skripten, die für die Bash-Befehlsshell geschrieben wurden. Überprüfen Sie Shell-Skripte mit Fehlern / Syntaxfehlern mit dem Shellcheck-Programm (oder auf dem Web-Shellcheck-Server unter https://shellcheck.net), bevor Sie sie hier veröffentlichen. Fragen zur interaktiven Verwendung von Bash sind bei Super User eher themenbezogen als bei Stack Overflow.