Заменить заголовок указанного столбца именем файла.

Заменить заголовок указанного столбца именем файла.

У меня много 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

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

Связанный контент