我想使用文件samples.txt的每一行作为正则表达式,并从input.txt中打印与之匹配的整个列。
samples.txt
aa
bb
cc
input.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
output.txt
aa bb cc
1 3 8
5 7 8
我可以分别执行这些操作——在bash中读取每一行,然后将其用作正则表达式,然后分别使用正则表达式打印匹配的列,但是我不能将它们放在一起。有什么建议吗?
打印每个匹配的列,我可以使用:
awk 'NR==1 {for(i=1;i<=NF;i++) if ($i~/$line/) f=i;next} {print $f}' input.txt
并遍历文件中的每一行,作为正则表达式使用,如上所述:
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
In 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 "%st",$i;print x}' {samples,input}.txt
aa bb cc
1 3 8
5 7 8
这基本上是在第一个文件中以数组的形式收集样本。接下来,在第二行代码的第一行,将每个字段与样本进行比较,如果相同,则将其设置为1。
Then遍历每行,只打印数组中设置为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
我认为将input.txt
文件转置更容易,打印以给定单词开头的那些行,然后转置:
$ awk 'FNR==NR {a[$1]; next} $1 in a' samples <(transpose < input) | transpose
aa bb cc
1 3 8
5 7 8
读取file1
时使用awk 'FNR==NR {do_things; next} other_things' file1 file2
执行do_things
,读取file2
时使用other_things
。
在本例中,我们将samples
中的所有名称加载到数组a[]
中。然后,我们遍历input
数据并检查它的第一个字段是否在数组中。如果是,则该语句的计算结果为True,并打印该行。
transpose
是我在另一个答案中使用的函数:
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)
}
}'
}
如果你想要一个正则表达式比较,那么它是:
$ 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。