使用 awk 检查不同行的变量

发布于 2024-12-05 15:18:38 字数 334 浏览 2 评论 0原文

我想使用 awk 将多行不同长度的值合并到一行(如果它们匹配)。在以下第一个字段的示例匹配值中, 将第二个字段中的值聚合到列表中。

输入,示例 csv:

222;a;DB;a
222;b;DB;a
555;f;DB;a
4444;a;DB;a
4444;d;DB;a
4444;z;DB;a

输出:

222;a|b
555;f
4444;a|d|z

如何编写 awk 表达式(可能是其他 shell 表达式)来检查第一个字段值是否与下一行/上一行匹配,然后打印第二个字段值的列表,这些值聚合并由管道?

I want to combine values from multiple lines with different lengths using awk into one line if they match. In the following sample match values for first field,
aggregating values from second field into a list.

Input, sample csv:

222;a;DB;a
222;b;DB;a
555;f;DB;a
4444;a;DB;a
4444;d;DB;a
4444;z;DB;a

Output:

222;a|b
555;f
4444;a|d|z

How can I write an awk expression (maybe some other shell expression) to check if the first field value match with the next/previous line, and then print a list of second fields values aggregated and separated by a pipe?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

逆流 2024-12-12 15:18:38
awk '
  BEGIN {FS=";"}
  { if ($1==prev) {sec=sec "|" $2; }
    else { if (prev) { print prev ";" sec; };
           prev=$1; sec=$2; }}
  END { if (prev) { print prev ";" sec; }}'

根据您的要求,这会检查连续的行。

awk '
  BEGIN {FS=";"}
  { if ($1==prev) {sec=sec "|" $2; }
    else { if (prev) { print prev ";" sec; };
           prev=$1; sec=$2; }}
  END { if (prev) { print prev ";" sec; }}'

This, as you requested, checks the consecutive lines.

殤城〤 2024-12-12 15:18:38

这个单线有用吗?

 awk -F';' '{a[$1]=a[$1]?a[$1]"|"$2:$2;} END{for(x in a) print x";"a[x]}' file

在这里测试:

kent$  cat a
222;a;DB;a
222;b;DB;a
555;f;DB;a
4444;a;DB;a
4444;d;DB;a
4444;z;DB;a

kent$  awk -F';' '{a[$1]=a[$1]?a[$1]"|"$2:$2;} END{for(x in a) print x";"a[x]}'  a
555;f
4444;a|d|z
222;a|b

如果你想保持排序,请在末尾添加 |sort

does this oneliner work?

 awk -F';' '{a[$1]=a[$1]?a[$1]"|"$2:$2;} END{for(x in a) print x";"a[x]}' file

tested here:

kent$  cat a
222;a;DB;a
222;b;DB;a
555;f;DB;a
4444;a;DB;a
4444;d;DB;a
4444;z;DB;a

kent$  awk -F';' '{a[$1]=a[$1]?a[$1]"|"$2:$2;} END{for(x in a) print x";"a[x]}'  a
555;f
4444;a|d|z
222;a|b

if you want to keep it sorted, add a |sort at the end.

好倦 2024-12-12 15:18:38

有点复杂,但可以完成工作:

awk -F';' \
'{
  if (a[$1]) {
    a[$1]=a[$1] "|" $2
  } else {
    a[$1]=$2
  }
 }
 END {
   for (k in a) {
     print k ";" a[k]
   }
 }' file

Slightly convoluted, but does the job:

awk -F';' \
'{
  if (a[$1]) {
    a[$1]=a[$1] "|" $2
  } else {
    a[$1]=$2
  }
 }
 END {
   for (k in a) {
     print k ";" a[k]
   }
 }' file
情深已缘浅 2024-12-12 15:18:38

假设您已将字段分隔符 (-F) 设置为 ; :

{
   if ( $1 != last ) { print s; s = ""; }
   last = $1;
   s = s "|" $2;
} END {
   print s;
}

第一行和第一个字符略有错误,但这是读者的练习:-)。两个简单的 if 就足以解决这个问题。

(编辑:错过了最后一行。)

Assuming that you have set the field separator ( -F ) to ; :

{
   if ( $1 != last ) { print s; s = ""; }
   last = $1;
   s = s "|" $2;
} END {
   print s;
}

The first line and the first character are slightly wrong, but that's an exercise for the reader :-). Two simple if's suffice to fix that.

(Edit: Missed out last line.)

鲜肉鲜肉永远不皱 2024-12-12 15:18:38

这应该有效:

命令:

awk -F';' '{if(a[$1]){a[$1]=a[$1]"|"$2}else{a[$1]=$2}}END{for (i in a){print i";" a[i] }}' fil

输入:

222;a;DB;a
222;b;DB;a
555;f;DB;a
4444;a;DB;a
4444;d;DB;a
4444;z;DB;a

输出:

222;a|b
555;f
4444;a|d|z

this should work:

Command:

awk -F';' '{if(a[$1]){a[$1]=a[$1]"|"$2}else{a[$1]=$2}}END{for (i in a){print i";" a[i] }}' fil

Input:

222;a;DB;a
222;b;DB;a
555;f;DB;a
4444;a;DB;a
4444;d;DB;a
4444;z;DB;a

Output:

222;a|b
555;f
4444;a|d|z
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文