使用使用awk创建的数组作为另一个awk脚本中的变量



我正试图使用awk来提取数据,该条件语句包含使用另一个awk脚本创建的数组。

我用于创建数组的awk脚本如下:

array=($(awk 'NR>1 { print $1 }' < file.tsv))

然后,在其他awk脚本中使用此数组

awk var="${array[@]}"  'FNR==1{ for(i=1;i<=NF;i++){ heading[i]=$i } next } { for(i=2;i<=NF;i++){ if($i=="1" && heading[i] in var){ close(outFile); outFile=heading[i]".txt"; print ">kmer"NR-1"n"$1 >> (outFile) }}}' < input.txt

但是,当我运行此程序时,会出现以下错误。

awk: fatal: cannot open file 'foo' for reading (No such file or directory)

我已经看过多篇关于为什么会出现这种错误以及如何在awk中正确实现shell变量的文章,但到目前为止,这些文章都不起作用。但是,当删除shell变量并运行脚本时,它确实有效。

awk 'FNR==1{ for(i=1;i<=NF;i++){ heading[i]=$i } next } { for(i=2;i<=NF;i++){ if($i=="1"){ close(outFile); outFile=heading[i]".txt"; print ">kmer"NR-1"n"$1 >> (outFile) }}}' < input.txt

我真的很需要那个条件语句,但不知道在awk中实现bash变量有什么错,希望能得到一些帮助。

提前Thx。

特定的错误消息是因为您忘记了-vvar=前面(它应该是awk -v var=,而不仅仅是awk var=(,但正如其他人所指出的,您不能在awk命令行上设置数组变量。还要注意,代码中的arrayshell数组,而不是awk阵列,shell和awk是两个完全不同的工具,每个工具都有自己的语法、语义、作用域等。

以下是如何真正做到你想做的事情:

array=( "$(awk 'BEGIN{FS=OFS="t"} NR>1 { print $1 }' < file.tsv)" )
awk -v xyz="${array[*]}" '
BEGIN{ split(xyz,tmp,RS); for (i in tmp) var[tmp[i]] }
... now use `var` as you were trying to ...
'

例如:

$ cat file.tsv
col1    col2
a b     c d e
f g h   i j

$ cat -T file.tsv
col1^Icol2
a b^Ic d e
f g h^Ii j

$ awk 'BEGIN{FS=OFS="t"} NR>1 { print $1 }' < file.tsv
a b
f g h

$ array=( "$(awk 'BEGIN{FS=OFS="t"} NR>1 { print $1 }' < file.tsv)" )

$ awk -v xyz="${array[*]}" '
BEGIN {
split(xyz,tmp,RS)
for (i in tmp) {
var[tmp[i]]
}
for (idx in var) {
print "<" idx ">"
}
}
'
<f g h>
<a b>

在单个awk:中处理两个文件更容易、更高效

编辑:修复了评论中的问题,感谢@EdMorton

awk '
FNR == NR {
if ( FNR > 1 )
var[$1]
next
}
FNR == 1 {
for (i = 1; i <= NF; i++)
heading[i] = $i
next
}
{
for (i = 2; i <= NF; i++)
if ( $i == "1" && heading[i] in var) {
outFile = heading[i] ".txt"
print ">kmer" (NR-1) "n" $1 >> (outFile)
close(outFile)
}
}
' file.tsv input.txt

您可以将字符串存储在变量中,然后使用split函数将其转换为数组,考虑以下简单示例,让file1.txt内容为

A B C
D E F
G H I

CCD_ 9内容为

1
3
2

然后

var1=$(awk '{print $1}' file1.txt)
awk -v var1="$var1" 'BEGIN{split(var1,arr)}{print "First column value in line number",$1,"is",arr[$1]}' file2.txt

给出输出

First column value in line number 1 is A
First column value in line number 3 is G
First column value in line number 2 is D

说明:我存储第一个awk命令的输出,然后将其用作第二个awk命令中split函数的第一个参数免责声明:此解决方案假设所有涉及的文件都具有符合默认GNUAWK行为的分隔符,即一个或多个空白始终是分隔符。

(在gawk 4.2.1中测试(

最新更新