У меня много 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, и столбец № 10 этой строки 237 содержит $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, а столбец № 10 этой строки 237 содержит $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
команда не выполняется, правая часть &&
не выполняется, а исходные данные сохраняются в безопасности.