Verwenden Sie sed, um das letzte Leerzeichen in jeder Zeile durch ein Komma zu ersetzen, und entfernen Sie dann alle Leerzeichen

7

Ich habe eine zweispaltige, durch Leerzeichen getrennte TXT-Datei, aber die erste Spalte enthält Leerzeichen (die Fehler sind). Ich muss es in eine CSV konvertieren, aber ich kann nicht einfach alle Leerzeichen durch Kommas ersetzen.

Beispieleingabe:

gi|118592783|ref|ZP_01550172.1|_biphenyl-2  3-diol_1    2-dioxygenase_[Stappia_aggregata_IAM_12614] 1

Gewünschte Ausgabe:

gi|118592783|ref|ZP_01550172.1|_biphenyl-23-diol_12-dioxygenase_[Stappia_aggregata_IAM_12614],1

Wie kann ich sed(oder etwas anderes) verwenden, um das letzte Leerzeichen in einer Reihe durch ein Komma zu ersetzen und dann alle verbleibenden Leerzeichen zu entfernen? Würde das effektiv eine CSV-Datei erstellen?

Zoey RW
quelle

Antworten:

8

Etwas wie:

sed -r 's/(.*) /\1,/; s/ //g'

Die erste Auswechslung, die gierig ist, deckt alle bis auf das letzte Feld in der Gruppe ab und ersetzt das letzte durch ein ,. Der zweite wird dann den Rest eliminieren.

muru
quelle
Bei mir funktioniert es nicht richtig: / (ersetzt ein Leerzeichen zwischen der Zeile außer dem letzten).
Ravexina
@ Thor Jetzt ist es richtig;)
Ravexina
1
@Thor danke! Meine Tastatur ist eine PITA, seit ich Kaffee darauf verschüttet habe. :(
Muru
4
@muru Regel von IT, Software Engineering und Engineering # 1: Du sollst deinen Kaffee nicht verschütten, sondern ihn Tasse für Tasse vollständig konsumieren
Sergiy Kolodyazhnyy
1
Einfachere Lösung : sed 's/.* /&,/;s/ //g'. Wenn sowieso alle Leerzeichen entfernt werden, macht es keinen Unterschied, das Komma nach dem letzten Leerzeichen anzuhängen, sodass Sie dieses \1Zeug und die erweiterte RE nicht benötigen .
Philippos
3

Dies würde den Job machen:

sed -r "s/\s([0-9]+$)/,\1/" filename.txt | tr -d ' '

oder:

sed -r "s/\s([0-9]+$)/,\1/; s/\s//g" filename.txt

Eingabebeispiel:

gi|118592783|ref|ZP_01550172.1|_biphenyl-2 3-diol_1    2-dioxygenase_[Stappia_aggregata_IAM_12614] 1

Ausgabe:

gi|118592783|ref|ZP_01550172.1|_biphenyl-23-diol_12-dioxygenase_[Stappia_aggregata_IAM_12614],1
Ravexina
quelle
1
Ich mag das Beispiel mit, trda es explizit ist und daher für neue Benutzer besser lesbar ist, aber das zweite sedist auch ein gutes Zitat.
Sergiy Kolodyazhnyy
3

Hier ist ein geekiger Weg - mit einer sed-Schleife.

  1. Wenn das Muster nur ein Leerzeichen enthält, ersetzen Sie es durch ein Komma
  2. (andernfalls) Ersetzen Sie das erste Leerzeichen durch nichts und gehen Sie zu 1

was wir in GNU sed schreiben können als

sed -e :1 -e '/^[^ ]* [^ ]*$/ s/ /,/' -e 's/ //; t1'

Testen:

$ echo 'gi|118592783|ref|ZP_01550172.1|_biphenyl-2  3-diol_1    2-dioxygenase_[Stappia_aggregata_IAM_12614] 1' | 
  sed -e :1 -e '/^[^ ]* [^ ]*$/ s/ /,/' -e 's/ //; t1'
gi|118592783|ref|ZP_01550172.1|_biphenyl-23-diol_12-dioxygenase_[Stappia_aggregata_IAM_12614],1
Steeldriver
quelle
3

Perl

$ perl -ne 's/\s//g;s/^(.*)([[:digit:]])$/\1,\2/;print' input.txt                                                                                    
gi|118592783|ref|ZP_01550172.1|_biphenyl-23-diol_12-dioxygenase_[Stappia_aggregata_IAM_12614],1

oder kürzer:

perl -pe 's/\s//g;s/^(.*)([[:digit:]])$/\1,\2/' input.txt 

Tatsächlich ist dies das Gegenteil von Murus Ansatz: Wir entfernen zuerst alle Leerzeichen und gruppieren dann alles vor dem letzten Element (Gruppe \1) und dem letzten Element (Gruppe \2, zwei, die zufällig eine Ziffer sind). Wir ersetzen die Zeile durch Gruppe \1und \2werden durch Komma getrennt.

Beachten Sie, dass ([[:digit:]])dies geändert werden kann, um (.)auf ein beliebiges Zeichen zu verweisen, falls dies erforderlich ist (dh wenn wir erwarten, dass das letzte Zeichen von einem beliebigen Typ ist), oder dass wir ([[:graph:]])nur druckbare Zeichen verwenden können

Sergiy Kolodyazhnyy
quelle