我有这样的文件:
pw1jc5ssyt6hx618,254343
ysezaratlycpuggl,254333
pht92h4adr3mrbz3,254343
hguvgstqxu3gowfg,254344
gqjp2rsjmk1a2v9c,254333
twdzyi2ddbnrfknd,254333
gcmj7krrx5x6nf8r,254341
tpqorqbyrg1nmm7s,254333
alnac47rt8d4ege3,254343
Run Code Online (Sandbox Code Playgroud)
我想根据第二列合并这个文件,-
作为分隔符,这样结果看起来像这样:
254343,pw1jc5ssyt6hx618-pht92h4adr3mrbz3-alnac47rt8d4ege3
254333,ysezaratlycpuggl-gqjp2rsjmk1a2v9c-twdzyi2ddbnrfknd-tpqorqbyrg1nmm7s
254344,hguvgstqxu3gowfg
254341,gcmj7krrx5x6nf8r
Run Code Online (Sandbox Code Playgroud)
awk
是你的朋友
$ cat 299360
ipw1jc5ssyt6hx618,254343
ysezaratlycpuggl,254333
pht92h4adr3mrbz3,254343
hguvgstqxu3gowfg,254344
gqjp2rsjmk1a2v9c,254333
twdzyi2ddbnrfknd,254333
gcmj7krrx5x6nf8r,254341
tpqorqbyrg1nmm7s,254333
alnac47rt8d4ege3,254343
$ awk -v FS="," '/^$/{next} # for empty line go to next record
{if(NR==1){ # checking for first record
f2[$2]=$1;next} # Adding $1 to array f2 at index $2
else{
if($2 in f2){ # Check if $2 is already an index in f2
f2[$2]=f2[$2]"-"$1;next #appending "-$1" to current value
}
else{
f2[$2]=$1;next
}
}}
END{ # This line will be processed at the end
for(i in f2){ # for all the indexes i in f2
printf "%s,%s\n",i,f2[i] #printing in the desired format
}
}
' 299360
254341,gcmj7krrx5x6nf8r
254333,ysezaratlycpuggl-gqjp2rsjmk1a2v9c-twdzyi2ddbnrfknd-tpqorqbyrg1nmm7s
254343,pw1jc5ssyt6hx618-pht92h4adr3mrbz3-alnac47rt8d4ege3
254344,hguvgstqxu3gowfg
Run Code Online (Sandbox Code Playgroud)
解释
FS=","
– FS 是 awk 的内置变量,代表字段分隔符。将字段分隔符,
设置,
为将设置为分隔符。$1
,$2
等等。'awk-script-goes-here'
NR
是一个 awk 内置变量,代表记录编号(当前正在处理的记录编号)。默认情况下,每一行都是一条记录。f2[$2]=$1
我们建立一个f2
以 field2(即$2
)为索引的关联数组。$2 in f2
检查索引是否已经存在于数组中。if-else
和printf
不言自明。END
awk 中的块只在最后执行;即,在处理完所有记录之后。for(i in f2)
是一个 for?loop 构造,用于解析 awk 中的关联数组。这是另一种说法,for every index i in f2 do something
for
循环可能不会按顺序打印数组。不过,您可以使用sort
bash 命令对数组进行排序。next
不处理后面的命令就转到下一条记录。/pattern/
用于在AWK的图案检查; 该模式^$
检查空行。参考
如果你想成为 awk 的专家,Effective awk Programming是必读的。
丑的单线
awk -v FS="," '/^$/{next}{if(NR==1){f2[$2]=$1;next}else{if($2 in f2){f2[$2]=f2[$2]"-"$1;next}else{f2[$2]=$1;next}}}END{for(i in f2){printf "%s,%s\n",i,f2[i]}}' 299360
Run Code Online (Sandbox Code Playgroud)
注意:理想情况下,在 awk 脚本中硬编码换行符不是一个好主意,如printf "%s,%s\n",i,f2[i]
. 您可以将其替换printf "%s,%s\n",i,f2[i];print
为额外的便携性。
使用 GNU datamash:
datamash -t, -s -g 2 collapse 1 <data.txt | sed 's/,/-/2g'
Run Code Online (Sandbox Code Playgroud)
结果:
254333,ysezaratlycpuggl-gqjp2rsjmk1a2v9c-twdzyi2ddbnrfknd-tpqorqbyrg1nmm7s
254341,gcmj7krrx5x6nf8r
254343,pw1jc5ssyt6hx618-pht92h4adr3mrbz3-alnac47rt8d4ege3
254344,hguvgstqxu3gowfg
Run Code Online (Sandbox Code Playgroud)