用檔案名稱替換給定列的標題

用檔案名稱替換給定列的標題

我有很多 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

在此輸入影像描述@YetAnotherUser,請查看有關我的請求的示例文件的圖像:“用文件名替換給定列的標題”

答案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命令失敗,右側部分&& 不被執行,原始資料將保持安全

相關內容