Ersetzen Sie die Überschrift einer bestimmten Spalte durch den Dateinamen

Ersetzen Sie die Überschrift einer bestimmten Spalte durch den Dateinamen

Ich habe viele VCF-Dateien

HR001.vcf
HR002.vcf
HR003.vcf
HR004.vcf
HR005.vcf
HR006.vcf
HR007.vcf
HR008.vcf
.
.

Im10. SpalteBei JEDER Datei lautet die Spaltenüberschrift $i. In jeder Datei möchte ich $i durch den Basisnamen der Dateien ersetzen. Beispielsweise für die Datei HR001.vcf $i=HR001, für HR002.vcf $i=HR002 usw. ... gibt es eine einfache Möglichkeit, dies unter Unix zu tun? Ich besitze ein MacBook Pro, bin aber neu darin. Dies sind eigentlich VCF-Dateien mit tabulatorgetrennten Feldern. Ja, jede Datei hat 236 Zeilen, die übersprungen werden sollten. Mich interessiert die Zeile, die mit #CHROM beginnt, also Zeile Nr. 237, und die Spalte Nr. 10 dieser Zeile 237 enthält $i

Antwort1

Ich würde verwenden perl:

perl -F'\t' -i -lape '
  if ($F[0] eq "#CHROM" && $F[9] eq q($i)) {
    $F[9] = ($ARGV =~ s/\.vcf$//r);
    $_ = join "\t", @F
  }' -- *.vcf

Antwort2

Ein Skript wie dieses kann die Arbeit erledigen:

cd /path/to/direcrtory
for i in *.vcf
do
awk '{if (FNR==1) $10=FILENAME; print}' "$i" >"$i.tmp" && mv -f "$i.tmp" "$i"
done

Die "Magie" liegt in der Variable FILENAME, die awkden Eingabedateinamen enthält

Antwort3

Bildbeschreibung hier eingeben@YetAnotherUser, bitte sehen Sie sich ein Bild der Beispieldatei zu meiner Anfrage an: „Ersetzen Sie die Kopfzeile einer bestimmten Spalte durch den Dateinamen“

Antwort4

Vorausgesetzt, Ihre Dateien sind durch Leerzeichen getrennt, sollte dies funktionieren:

for f_name in HR[0-9]*.vcf; do
    awk -v f="${f_name%.*}" 'NR == 1 {$10 = f}1' "$f_name" > "$f_name.tmp"
    mv "$f_name.tmp" "$f_name"
done

Gehen Sie durch das Verzeichnis und holen Sie sich jede vcfDatei. Entfernen Sie dann die Erweiterung aus dem Dateinamen mit ${f_name%.*}und übergeben Sie sie als Parameter an awk.

awkwird dies als Dateiname für den Austausch verwenden.NOTIZ: Dies muss im selben Verzeichnis wie die vcfDatei ausgeführt werden. Wenn Sie es von einem anderen Pfad aus ausführen möchten, verwenden Sie Folgendes:

for f_name in /some/full/path/HR[0-9]*.vcf; do
    # remove the path
    f="${f_name##*/}"
    awk -v f="${f%.*}" 'NR == 1 {$10 = f}1' "$f_name" > "$f_name.tmp"
    mv "$f_name.tmp" "$f_name"
done

Wenn die Dateien nicht durch Leerzeichen getrennt sind awk FS, beheben Sie das Problem.

BEARBEITEN FÜR NEUE ANFORDERUNGEN UND BASIEREND AUF VERBESSERUNGEN VON @Ed Morton

Mich interessiert die Zeile, die mit #CHROM beginnt, also Zeile 237, und die Spalte 10 dieser Zeile 237 enthält $i

for f_name in /some/full/path/HR[0-9]*.vcf; do
    # remove the path
    f="${f_name##*/}"
    awk -F'\t' -v f="${f%.*}" 'NR == 237 {$10 = f}1' "$f_name" > "$f_name.tmp" && mv "$f_name.tmp" "$f_name"
done

Diese neue Version des Skripts ersetzt den Dateinamen nur in dem gewünschten Feld ($10 = f)und in der gewünschten Zeile (NR == 237). Der awkParameter -F\tlegt fest, wie awkZeilen angezeigt und in Felder aufgeteilt werden.

Nochmals vielen Dank an @Ed Morton, der die ursprünglichen Skripte verbessert hat: Wie Sie sehen können, ist die Anweisung: mv "$f_name.tmp" "$f_name"das ist der Befehl zum Überschreiben der alten Datei mit dem Inhalt der neuen (erstellt von awk) in einer Zeile zusammengefasst: auf diese Weise wird der rechte Teil der Datei nicht ausgeführt awk '' file > tmp && mv tmp file, wenn der Befehl fehlschlägt , und die Originaldaten bleiben sicher erhaltenawk&&

verwandte Informationen