我有很多 vcf 文件
HR001.vcf
HR002.vcf
HR003.vcf
HR004.vcf
HR005.vcf
HR006.vcf
HR007.vcf
HR008.vcf
.
.
在裡面第10欄每個文件的列標題是 $i。在每個文件中,我想用文件的基本名稱替換 $i 。例如,對於檔案 HR001.vcf,$i=HR001,對於 HR002.vcf $i=HR002 等...是否有一種簡單的方法可以在 unix 中執行此操作。我擁有一台 MacBook Pro,但我對此很陌生。這些實際上是帶有製表符分隔欄位的 VCF 檔案。是的,每個檔案有 236 行應該被跳過。我對以 #CHROM 開頭的行感興趣,即第 237 行,第 237 行的第 10 列包含 $i
答案1
我會用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
答案2
像這樣的腳本可以完成這項工作:
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
「魔法」位於包含輸入檔名FILENAME
的變數中awk
答案3
答案4
假設您的檔案是以空格分隔的,這應該可以工作:
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
在目錄內循環並取得每個vcf
檔案。然後從檔案名稱中刪除擴展名${f_name%.*}
並將其作為參數傳遞給awk
.
awk
將使用它作為文件名來進行修改。筆記:這需要在vcf
檔案的同一目錄中運行,如果您想從另一個路徑運行它,請使用以下命令:
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
如果檔案不是空格分隔修復awk FS
。
根據@Ed Morton 的改進,針對新請求進行編輯
我對以 #CHROM 開頭的行感興趣,即第 237 行,第 237 行的第 10 列包含 $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
($10 = f)
這個新版本的腳本僅在您喜歡的欄位和您想要的行中替換檔案名稱(NR == 237)
。此awk
參數-F\t
設定如何awk
查看行並在欄位中拆分行。
再次感謝 @Ed Morton,它改進了原始腳本:正如您所看到的語句:mv "$f_name.tmp" "$f_name"
這是用新文件(由 生成)的內容覆蓋舊文件的命令awk
被壓縮在一行中:awk '' file > tmp && mv tmp file
這樣,如果awk
命令失敗,右側部分&&
不被執行,原始資料將保持安全