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
、1行に凝縮されています。awk '' file > tmp && mv tmp file
このようにして、awk
コマンドが失敗した場合、 の適切な部分は&&
実行されず、元のデータは安全に保持されます。