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 awk
den Eingabedateinamen enthält
Antwort3
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 vcf
Datei. Entfernen Sie dann die Erweiterung aus dem Dateinamen mit ${f_name%.*}
und übergeben Sie sie als Parameter an awk
.
awk
wird dies als Dateiname für den Austausch verwenden.NOTIZ: Dies muss im selben Verzeichnis wie die vcf
Datei 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 awk
Parameter -F\t
legt fest, wie awk
Zeilen 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
&&