我有以下两个文件。
query.txt
pumpkin
kiwi
subject.tsv
kiwifruit something green
melon something red
pumpkinhead something orange
我想遍历query.txt并检查每一行,如果subject.tsv中的任何第一个字段都包含该行。如果是,则将选项卡以及subject.tsv中的第三个字段添加到该行。 query.txt中各行的顺序应保留在输出中。
我尝试了以下方法。
while read query; do echo -e $query"\t"; awk '$1 ~ "$query" {print $3}' subject.tsv; done < query.txt
所需的输出:
pumpkin orange
kiwi green
实际输出:
pumpkin
kiwi
答案 0 :(得分:2)
Bash不会对单引号('
)中公开的字符串执行变量扩展,因此脚本的问题在这里:
'$1 ~ "$query" {print $3}'
一定是这样的:
'$1 ~ '"$query"' {print $3}'
但是,即使在修复该脚本后,它的效率仍然很低并且容易出错。因此,我建议您在单个awk调用中执行以下操作:
awk -F'\t' -v OFS='\t' '
NR==FNR { a[$0] = $3; next } {
for (b in a) {
if (index(b, $0)) {
print $0, a[b]
break
}
}
}' subject.tsv query.txt
答案 1 :(得分:1)
尽管问题中缺少很多信息,例如查询文件是否包含唯一字符串?还是主题文件包含重复的字符串?但鉴于当前文件和要求,请在下面给出答案,由于它是基于awk的,因此它也应适用于大型文件:
awk ' BEGIN{OFS="\t"}
FILENAME ~ /subject.tsv$/ {
color[$1]=$3
}
FILENAME ~ /query.txt$/ {
for (i in color) {
if ( i ~ $1 ) print $1, color[i]
}
}' subject.tsv query.txt
下面是输出:
pumpkin orange
kiwi green
答案 2 :(得分:0)
在使用while
的代码版本中,您需要使用awk
选项将要搜索的字符串传递给-v
命令,否则awk
将处理所有作为纯字符串。
例如,如果要传递变量query
包含的字符串'pumpkin',则需要这样做:
query="pumpkin"; awk -v query=$query '$1 ~ query' subject.tsv
-v
用于声明一个变量,该变量使用awk
之外的变量的内容。您可以看到awk
-v var = val
--assign var = val
在程序开始执行之前,将值val分配给变量var。这样的变量值可用于AWK程序的BEGIN规则。
因此,您可以尝试通过将query
传递到awk
来相应地修改代码。
答案 3 :(得分:0)
这里是bash解决方案
while read pattern; do
column1=$(cut -d " " -f1 subject.tsv | grep "$pattern")
allcolumns=$(echo "$pattern $(grep $column1 subject.tsv)")
echo $allcolumns | cut -d " " -f1,4
done < query.txt
说明
阅读query.txt的所有行
while read pattern; do
...
done < query.txt
在第1列中找到搜索模式
while read pattern; do
column1=$(cut -d " " -f1 subject.tsv | grep "$pattern")
echo $column1
done < query.txt
输出
pumpkinhead
kiwifruit
将query.txt中的模式与subject.tsv中的匹配项合并
while read pattern; do
column1=$(cut -d " " -f1 subject.tsv | grep "$pattern")
allcolumns=$(echo "$pattern $(grep $column1 subject.tsv)")
echo $allcolumns
done < query.txt
输出
pumpkin pumpkinhead something orange
kiwi kiwifruit something green
首先从合并中提取最后一个字段
echo $allcolumns | cut -d " " -f1,4
输出
pumpkin orange
kiwi green
答案 4 :(得分:0)
您可以尝试使用此命令行Perl
$ perl -lane ' BEGIN { open($fh,"query.txt");@q=<$fh>;chomp(@q) } @s=/(\S+)/g;
/$q[0]/ and print "$q[0] $s[2]"; if(eof) { close($ARGV); shift @q}; ' subject.tsv subject.tsv
使用您的输入。
$ perl -lane ' BEGIN { open($fh,"query.txt");@q=<$fh>;chomp(@q) } @s=/(\S+)/g;
/$q[0]/ and print "$q[0] $s[2]"; if(eof) { close($ARGV); shift @q}; ' subject.tsv subject.tsv
pumpkin orange
kiwi green
$