Расширение параметра не работает при использовании внутри Awk для одной из записей столбца

Система: Linux. Баш 4.

У меня есть следующий файл, который будет считан в сценарий как переменная:

/path/sample_A.bam A 1
/path/sample_B.bam B 1
/path/sample_C1.bam C 1
/path/sample_C2.bam C 2 

Я хочу добавить "_string" в конце имени файла первого столбца, но перед расширением (.bam). Это немного сложнее, потому что в начале имени содержится путь.

Желаемый вывод:

/path/sample_A_string.bam A 1
/path/sample_B_string.bam B 1
/path/sample_C1_string.bam C 1
/path/sample_C2_string.bam C 2 

Моя попытка: я сделал следующий скрипт (я запустил: bash script.sh):

List=${1};
awk -F'\t' -vOFS='\t' '{ $1 = "${1%.bam}" "_string.bam" }1' < ${List} ;

И его вывод был:

${1%.bam}_string.bam
${1%.bam}_string.bam
${1%.bam}_string.bam
${1%.bam}_string.bam

Проблема: я следовал идее использования awk для этой замены, как в этой теме https://unix.stackexchange.com/questions/148114/how-to-add-words-to-an-existing-column, но расширение параметра ${1%.bam} это явно не распознается AWK, как я намерен. Кто-нибудь знает правильный синтаксис для этой части кода? Эта часть должна была означать "все первые записи первого столбца, кроме последней части.bam". Я использовал ${1%.bam}, потому что он работает в Bash, но AWK - это другой язык, и, вероятно, он отличается. Спасибо!

4 ответа

Решение

Если я правильно понял ваше требование, не могли бы вы попробовать следующее.

val="_string"
awk -v value="$val" '{sub(".bam",value"&")} 1'  Input_file

Краткое объяснение: -v value означает передачу переменной оболочки с именем val значение в переменную awk variable Вот. Затем с помощью sub функция awk подставить строку .bam со строковым значением вместе с .bam значение, которое обозначается & тоже. Тогда упомяну 1 означает печать отредактированной / нередактированной строки.

Почему попытка ОП не сработала: Уважаемый ОП. в awk мы не можем передавать переменные оболочки напрямую, не упоминая их в awk язык. Так что то, что вы пытаетесь, НЕ примет это как awk переменная, а не будет принимать его как строку и печатать как есть. Я уже упоминал в своем объяснении выше, как определить переменные оболочки в awk тоже.

ПРИМЕЧАНИЕ: если у вас есть несколько случаев .bam тогда, пожалуйста, измените sub в gsub в приведенном выше коде. Также, если ваш Input_file является разделителем табуляции, используйте awk -F'\t' в приведенном выше коде.

Обратите внимание, что расширение параметра, к которому вы применили $1 не будет применяться внутри awk как весь командный орган awk команда передается в '..' который отправляет содержимое буквально, не применяя разбор оболочки. Отсюда и строка "${1%.bam}" передается как есть в первый столбец.

Вы можете сделать это полностью в Awk

awk -F'\t' 'BEGIN { OFS = FS }{ n=split($1, arr, "."); $1 = arr[1]"_string."arr[2] }1'  file

Код в основном разделяет содержимое $1 с разделителем . в массив arr в контексте Awk, Таким образом, часть строки до первого . хранится в arr[1] и последующие поля разделения сохраняются в следующих индексах массива. Мы воссоздаем имя файла по вашему выбору, объединяя записи массива с _string в части имени файла без расширения.

sed -i 's/\.bam/_string\.bam/g' myfile.txt

Это единственная строка с sed. Просто замените.bam на _string.bam

Вы можете попробовать этот способ с помощью awk:

awk -v a='_string' 'BEGIN{FS=OFS="."}{$1=$1 a}1' infile
Другие вопросы по тегам