Bash 在文本b中查找文本a中的所有值,并在其旁边键入其他文件中的其他列(使用awk)
a、 文本 b、 文本 现在是b.txt中的第二列值,我想知道它们是否存在于a.txt中,如果存在,我们在b.txt中的第二列(或其他文件)旁边写入a.txt中的第一列,以获得这样的文件,如:Bash 在文本b中查找文本a中的所有值,并在其旁边键入其他文件中的其他列(使用awk),bash,shell,sed,awk,statistics,Bash,Shell,Sed,Awk,Statistics,a、 文本 b、 文本 现在是b.txt中的第二列值,我想知道它们是否存在于a.txt中,如果存在,我们在b.txt中的第二列(或其他文件)旁边写入a.txt中的第一列,以获得这样的文件,如: 1,a 2,b 3,c 4,d .....(etc) 21,u 22,v 23,w 24,x 25,y 26,z 27,xono a 28,a yuli x 29,p dao 30,... 31,abc 32,def 33,ghi 34,jkl 35,mno 36,pqr 我知道你要的是awk,是的,这
1,a
2,b
3,c
4,d
.....(etc)
21,u
22,v
23,w
24,x
25,y
26,z
27,xono a
28,a yuli x
29,p dao
30,...
31,abc
32,def
33,ghi
34,jkl
35,mno
36,pqr
我知道你要的是
awk
,是的,这是可能的。也许您可以在perl
中基于此实现自己编写:
1,a
2,b
3,c,xd
4,d
.....(etc)
16,p
.....(etc)
21,u,xb,xd,xe,xf
22,v,xb,xe
23,w,xc,xe
24,x,xc
25,y,xa,xe
26,z,xa,xe,xf
27,xono a,xa
28,a yuli x,xd
29,p dao,xf
30,...
31,abc,xa
32,def,xb
33,ghi,xc
34,jkl,xd
35,mno,xe
36,pqr,xf
#/usr/bin/perl
严格使用;
我的%映射;
打开(my$a,'a.txt');
而(){
咀嚼;
我的($xx,@字母)=拆分(/,/);
每封我的$letter(@letters){
如果(!exists($mapping{$letter})){
$mapping{$letter}=[];
}
push(@{$mapping{$letter}},$xx);
}
}
打开(my$b,'b.txt');
而(){
咀嚼;
我的($num,$letter)=拆分(/,/);
if(存在($mapping{$letter})){
打印联接(“,”,$,@{$mapping{$letter}),“\n”;
}否则{
打印美元“\n”;
}
}
BASH/awk解决方案:
#!/usr/bin/perl
use strict;
my %mapping;
open(my $a, 'a.txt');
while (<$a>) {
chomp;
my ($xx, @letters) = split(/,/);
foreach my $letter (@letters) {
if (!exists($mapping{$letter})) {
$mapping{$letter} = [];
}
push(@{$mapping{$letter}}, $xx);
}
}
open(my $b, 'b.txt');
while (<$b>) {
chomp;
my ($num, $letter) = split(/,/);
if (exists($mapping{$letter})) {
print join(',', $_, @{$mapping{$letter}}), "\n";
} else {
print $_, "\n";
}
}
IFS=,&&whileread-rpq;开始执行awk-vp=“$p”-vq=“,$q”-F{
printf“%s%s”,p,q;gsub(/\./,“\\.”,q);r=q(,|$)}
$0~r{printf',%s',$1;next}END{print”“}a.txt;完成
这可能适合您(GNU-sed):
这将从
a.txt
构建一个sed脚本,该脚本针对b.txt
运行。在gawk
4.1版中,您可以使用数组数组。试一试
sed -r 's|^([^,]+)(,[^,]+)|/^[^,]+\2,?/s/$/,\1/\n\1|;/,/P;D' a.txt|sed -rf - b.txt
其中s.awk
为:
gawk -F, -f s.awk a.txt b.txt
NR==FNR{
对于(i=2;我看一看manjoin
当然。虽然循环使用IFS=,
将b.txt
中的每个值使用到shell变量p和q
。然后p和q
作为参数传递给awk。awk然后使用、a
、、b
等搜索a.txt中的每一行,如果找到了这些值打印。print
在BEGIN/END中的语句用于打印参数和新行。printf在BEGIN
中用于打印“1,a”,“2,b”,“26,z”
等,第二个printf用于打印”,v“”,xb“”,xe“
等。而awk-v p=“$p”-v q=“,$q”
是awk将shell变量传递给awk的一种方式。是的:D你真是个伟人!非常感谢!那么你添加了~r?是为了什么呢?$0~r
实际上是正则表达式匹配,因为我创建了var r
as,p(,|$)
这意味着,p
后面跟逗号或行尾。是的,我见过该解决方案,但因为它需要awk 4+版本,我无法在本地测试它,因为我的awk在OSX上,这不是4+我喜欢该解决方案,但它与重复字符串u、v、w、x、y、z:21、uxd 22、vxb 23、wxc 24、xxc 25、yxa的显示内容不匹配它应该显示:21,u,xb,xd,xe,xf 22,v,xb,xe 23,w,xc,xe 24,x,xc 25,y,xa,xe,xe 26,z,xa,xe,xf清晰且简单且令人惊奇!谢谢!对键的解释和打印$0键?我们每次找到正确的字符串时都会连接值?我已经用awk尝试过了(不是gawk)它也能工作。这正常吗?最后一个问题:-F-F是为了什么???@user3057111我确信我已经安装了Gnu Awk版本3.1.8和版本4.1.0。它不适用于verson 3.1。如果键入Awk--version
,你会得到什么?@user3057111它不是-F-F
。它是-F,
,首先是带set的将字段分隔符设置为,
,然后-f s.awk
告诉awk从文件s.awk
读取脚本。
sed -r 's|^([^,]+)(,[^,]+)|/^[^,]+\2,?/s/$/,\1/\n\1|;/,/P;D' a.txt|sed -rf - b.txt
gawk -F, -f s.awk a.txt b.txt
NR==FNR {
for (i=2; i<=NF; i++)
a[$i][$1]++
next
}
{
keys=""
if ($2 in a) {
for (i in a[$2])
keys= keys","i
}
print $0 keys
}