根据第二列合并一列

Roc*_*ock 1 awk gawk

我有这样的文件:

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)

sjs*_*sam 6

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)

解释

  1. FS=","– FS 是 awk 的内置变量,代表字段分隔符。将字段分隔符,设置,为将设置为分隔符。
  2. 您访问的领域$1$2等等。
  3. awk 脚本用单引号括起来;IE,'awk-script-goes-here'
  4. NR是一个 awk 内置变量,代表记录编号(当前正在处理的记录编号)。默认情况下,每一行都是一条记录。
  5. 通过f2[$2]=$1 我们建立一个f2以 field2(即$2)为索引的关联数组。
  6. $2 in f2 检查索引是否已经存在于数组中。
  7. if-elseprintf不言自明。
  8. ENDawk 中的块只在最后执行;即,在处理完所有记录之后。
  9. for(i in f2)是一个 for?loop 构造,用于解析 awk 中的关联数组。这是另一种说法,for every index i in f2 do something
  10. 请注意,上述for循环可能不会按顺序打印数组。不过,您可以使用sortbash 命令对数组进行排序。
  11. next 不处理后面的命令就转到下一条记录。
  12. /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为额外的便携性。


Sat*_*ura 6

使用 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)