我想将文件的每一行samples.txt用作正则表达式,并打印与input.txt匹配的整个列。
SAMPLES.TXT
s aa v dd jj bb ww cc
1 1 1 1 2 3 3 8
3 5 4 5 2 7 5 8
input.txt中
aa bb cc
1 3 8
5 7 8
output.txt的
awk 'NR==1 {for(i=1;i<=NF;i++) if ($i~/$line/) f=i;next} {print $f}' input.txt
我可以单独执行这些操作 - 在bash中读取每一行然后将其用作正则表达式,并使用正则表达式单独打印匹配列,但我不能将它们放在一起。有什么建议吗?
要打印我可以使用的每个匹配列:
while read line; do echo $line; done < samples.txt
并遍历每行的文件以用作上面的正则表达式:
while read line; do
awk 'NR==1 {for(i=1;i<=NF;i++) if ($i~/$line/) f=i;next} {print $f}' input.txt >> output.txt; done < samples.txt
但是我不能把这两个放在一起......
{{1}}
答案 0 :(得分:3)
我认为转置input.txt
文件更容易,打印那些以给定单词开头的行然后转置回来:
$ awk 'FNR==NR {a[$1]; next} $1 in a' samples <(transpose < input) | transpose
aa bb cc
1 3 8
5 7 8
在阅读awk 'FNR==NR {do_things; next} other_things' file1 file2
时使用do_things
执行file1
,在阅读other_things
时使用file2
。
在这种情况下,我们将samples
中的所有名称加载到数组a[]
中。然后,我们浏览input
数据并检查其第一个字段是否在数组中。如果是,则语句的计算结果为True,并打印该行。
transpose
是我在another answer中使用的函数:
transpose () {
awk '{for (i=1; i<=NF; i++) a[i,NR]=$i; max=(max<NF?NF:max)}
END {for (i=1; i<=max; i++)
{for (j=1; j<=NR; j++)
printf "%s%s", a[i,j], (j<NR?OFS:ORS)
}
}'
}
答案 1 :(得分:3)
在awk中
awk 'NR==FNR{a[$1]++;next}FNR==1{for(i=1;i<=NF;i++)b[i]=a[$i]}
{for(i=1;i<=NF;i++)if(b[i])printf "%s\t",$i;print x}' {samples,input}.txt
aa bb cc
1 3 8
5 7 8
这基本上在第一个文件中收集数组中的样本。接下来在第二行的第一行,将每个字段与样本进行比较,如果它们相同则将它们设置为1.
然后遍历每一行只打印数组中设置为1的字段。
删除以下(Kent | Fedorqui | Ed Morton)建议的尾随标签
awk 'NR==FNR{a[$1]++;next}FNR==1{for(i=1;i<=NF;i++)b[i]=a[$i]==1&&last=i}
{for(i=1;i<=NF;i++)if(b[i])printf "%s",$i (i==last?ORS:OFS)}' {samples,input}.txt
答案 2 :(得分:1)
如果您确实需要正则表达式比较,那么它是:
$ cat tst.awk
NR==FNR { colNames=(NR>1 ? colNames "|" : "") $0; next }
FNR==1 {
numCols = 0
for (i=1; i<=NF; i++) {
if ( $i ~ "("colNames")" ) {
colNrs[++numCols] = i
}
}
}
{
for (i=1; i<=numCols; i++) {
printf "%s%s", $(colNrs[i]), (i<numCols?OFS:ORS)
}
}
$ awk -f tst.awk samples.txt input.txt
aa bb cc
1 3 8
5 7 8
如果你真的想要一个字符串比较,那么:
$ cat tst2.awk
NR==FNR { colNames[$0]; next }
FNR==1 {
numCols = 0
for (i=1; i<=NF; i++) {
if ( $i in colNames ) {
colNrs[++numCols] = i
}
}
}
{
for (i=1; i<=numCols; i++) {
printf "%s%s", $(colNrs[i]), (i<numCols?OFS:ORS)
}
}
$ awk -f tst2.awk samples.txt input.txt
aa bb cc
1 3 8
5 7 8
要在多个输入文件上运行它,只需在awk命令行的末尾列出它们,不要编写shell循环来多次调用awk。