在列条目之一的 Awk 内部使用时,参数扩展不起作用

Parameter expansion not working when used inside Awk on one of the column entries

系统:Linux。 Bash 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 

我想在第一列文件名的末尾、扩展名 (.bam) 之前附加“_string”。由于在名称的开头包含路径,因此有点棘手。

期望输出:

/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 

我的尝试: 我做了以下脚本 (I 运行: bash script.sh):

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

它的输出是:

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

问题: 我遵循了在这个线程 https://unix.stackexchange.com/questions/148114/how-to-add-words-to-an-existing-column 中使用 awk 进行此替换的想法,但是 ${1%.bam} 的参数扩展显然没有像我预期的那样被 AWK 识别。有人知道那部分代码的正确语法吗?该部分的意思是 "all the first entry of the first column, except the last part of .bam"。我使用 ${1%.bam} 是因为它适用于 Bash,但 AWK 是另一种语言,可能有所不同。谢谢!

如果我理解正确你的要求,请你试试看。

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

简要说明: -v value表示将shell变量名为val的值传递给awk变量 variable 在这里。然后使用 awksub 函数将字符串 .bam 替换为字符串值以及 .bam 值,该值也由 & 表示。然后提到 1 意味着打印 edited/non-edtied 行。

为什么 OP 的尝试没有成功: 亲爱的,OP。在 awk 中,如果不在 awk 语言中提及它们,我们不能直接传递 shell 的变量。因此,您正在尝试的不会将其作为 awk 变量,而是将其作为字符串并按原样打印。我在上面的解释中也提到了如何在 awk 中定义 shell 变量。

注意: 如果 .bam 多次出现,请将 sub 更改为 gsub 在上面的代码中。另外,如果您的 Input_file 是 TAB 键,则在上面的代码中使用 awk -F'\t'

请注意,您在 </code> 上应用的参数扩展不会在 <code>awk 内作为整个命令应用 awk 命令的主体在 '..' 中传递,它按字面意思 发送内容 而不应用任何 shell 正在解析。因此,字符串 "${1%.bam}" 按原样传递到第一列。

您可以在 Awk

中完全做到这一点
awk -F'\t' 'BEGIN { OFS = FS }{ n=split(, arr, ".");  = arr[1]"_string."arr[2] }1'  file

代码基本上将</code>的内容用分隔符<code>.分割成一个数组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="."}{= a}1' infile