Behalten Sie nur einen bestimmten Teil einer Zeichenfolge in einer bestimmten Spalte

Behalten Sie nur einen bestimmten Teil einer Zeichenfolge in einer bestimmten Spalte

Ich habe eine Datei wie diese:

id  target_id                               length  eff_length
1   intron_FBgn0000721:20_FBgn0000721:18    1136    243.944268
1   intron_FBgn0000721:19_FBgn0000721:18    1122    240.237419
2   intron_FBgn0264373:2_FBgn0264373:3      56      0
3   intron_FBgn0027570:4_FBgn0027570:3      54      0

Für die 2. Spalte target_idmöchte ich nur die Zeichenfolge (nicht immer FBgnXXXX, manchmal andere Namen) zwischen intron_und der ersten behalten :. Die neue Ausgabedatei enthält also den einfacheren Wert für Spalte 2, aber der Rest der Datei bleibt gleich.

Ich habe es mit dem Sed-Befehl versucht, weiß aber nicht, wie ich den Teil löschen kann, den ich nicht brauche.

Antwort1

Verwenden von sedund column:

$ sed -E 's/ intron_([^:]*):[^[:space:]]*/ \1/' file | column -t
id  target_id    length  eff_length
1   FBgn0000721  1136    243.944268
1   FBgn0000721  1122    240.237419
2   FBgn0264373  56      0

Der Schlüssel dazu ist der Ersetzungsbefehl:

s/ intron_([^:]*):\S*/ \1/

Es sucht intron_und speichert alles nach intron_und vor dem ersten Doppelpunkt in der Variable 1. [^[:space:]]*stimmt mit allem von diesem Doppelpunkt bis zum Ende des Felds überein. All das wird durch den in der Variable gespeicherten Text ersetzt 1.

Verwendung awkmit tab-getrennter Ausgabe:

$ awk -v "OFS=\t" '{$2=$2;sub(/intron_/, "", $2); sub(/:.*/, "", $2); print}' file
id      target_id       length  eff_length
1       FBgn0000721     1136    243.944268
1       FBgn0000721     1122    240.237419
2       FBgn0264373     56      0

Erläuterung:

  • -v "OFS=\t"

    Dadurch wird als Ausgabefeldtrennzeichen ein Tabulatorzeichen festgelegt. Dies hilft beim Ausrichten der Spalten und macht möglicherweise columnunnötige Spalten überflüssig.

  • $2=$2

    Beim Drucken einer Zeile awkwird unser neu festgelegter Ausgabefeldtrenner nicht geändert, es sei denn, wir ändern etwas in der Zeile. Die Zuweisung des zweiten Felds zum zweiten Feld reicht aus, um sicherzustellen, dass die Ausgabe Tabulatoren enthält.

  • sub(/intron_/, "", $2)

    intron_Dadurch wird es aus dem zweiten Feld entfernt .

  • sub(/:.*/, "", $2)

    Dadurch wird alles nach dem ersten Doppelpunkt aus dem zweiten Feld entfernt.

  • print

    Dadurch wird unsere neue Zeile gedruckt.

Verwendung awkmit benutzerdefinierter Spaltenformatierung

Dies ist wie das obige, wird aber verwendet, printfdamit wir Spaltenbreiten und -ausrichtungen nach Wunsch individuell formatieren können:

$ awk  '{sub(/intron_/, "", $2); sub(/:.*/, "", $2); printf "%-3s %-12s %8s %3s\n",$1,$2,$3,$4}' file
id  target_id      length eff_length
1   FBgn0000721      1136 243.944268
1   FBgn0000721      1122 240.237419
2   FBgn0264373        56   0

Hier printf "%-3s %-12s %8s %3s\n",$1,$2,$3,$4wählt die Anweisung Spaltenbreiten und -ausrichtungen im gewohnten printfStil.

Verwenden sedund Konvertieren von Tabulator-getrennten zu Komma-getrennten

$ sed -E 's/ intron_([^:]*):[^[:space:]]*/ \1/; s/[[:space:]][[:space:]]*/,/g' file 
id,target_id,length,eff_length
1,FBgn0000721,1136,243.944268
1,FBgn0000721,1122,240.237419
2,FBgn0264373,56,0

Antwort2

Sie können Folgendes verwenden perl:

$ perl -anle '
    BEGIN {$" = "\t"}
    print "@{[@F]}" and next if $. == 1;
    $F[1] = $1 if /_([^:]*):/;
    print "@{[@F]}";
' file
id  target_id   length  eff_length
1   FBgn0000721 1136    243.944268
1   FBgn0000721 1122    240.237419
2   FBgn0264373 56      0
3   FBgn0027570 54      0

Erläuterung

  • -a: Jede Zeile automatisch in ein Array aufteilen @F.

  • BEGIN {$" = "\t"}: Wir setzen den Listentrenner auf Tabulator \t. Er wird verwendet, wenn ein Array oder ein Array-Segment in eine Zeichenfolge in doppelten Anführungszeichen interpoliert wird.

  • print "@{[@F]}" and next if $. == 1: Wir drucken die Kopfzeile und gehen zur nächsten Zeile über.

  • $F[1] = $1 if /_([^:]*):/: Wir erhalten den Wert zwischen _und dem ersten :und speichern ihn im zweiten Element in @F.

  • print "@{[@F]}": Drucken Sie einfach die gewünschte Ausgabe aus.

Antwort3

sed -e 'h;s/.*intron_[^:]*\(:[^[:space:]]*\).*/\1/;s/./ /g;;G;;s/\(.*\)\n\(.*\)intron_\([^:]*\):[^[:space:]]*/\2\3\1/' YourFile

In 1 sed (kein Pipe) wird die Spalte beibehalten. Es wird der Haltepuffer verwendet

Posix-Version (also --posixunter GNU sed)

verwandte Informationen