awk 分组依据和“减少”

awk 分组依据和“减少”

假设我有如下数据:

table_name id
table_name col_1
table_name col_2
another_table_name id
another_table_name col_1

如何使用awk第一列进行分组并将第二列减少为逗号分隔的列表?根据示例,输出应为:

table_name id,col_1,col_2
another_table_name id,col_1

这里的想法是我可以使用第二列基于jq第一列(键)中的数据构造一个 JSON 数组(值):

{"table_name": ["id", "col_1", "col_2"]}
{"another_table_name": ["id", "col_1"]}

除了 grouby /“reduce”步骤之外,一切正常;非常感谢任何帮助!

答案1

创建 JSON 结构的最简单选项是使用实用jo程序:

$ sed 's/[[:blank:]]\{1,\}/[]=/' file | jo -p
{
   "table_name": [
      "id",
      "col_1",
      "col_2"
   ],
   "another_table_name": [
      "id",
      "col_1"
   ]
}

该脚本通过将第一组空格或制表符替换sed为 来创建输入。根据您的示例数据,这会产生jo[]=

table_name[]=id
table_name[]=col_1
table_name[]=col_2
another_table_name[]=id
another_table_name[]=col_1

然后,该jo实用程序负责正确编码数据并创建 JSON 文档。如果您想要紧凑的输出,请将-p选项删除。jo


旧答案使用jq替代,但不处理需要 JSON 编码的数据:

假设没有数据需要特殊的 JSON 编码:

jq -n "$(awk '{ printf ".\"%s\" += [\"%s\"] |\n", $1, $2 } END { print "." }' file)"

或者

awk '{ printf ".\"%s\" += [\"%s\"] |\n", $1, $2 } END { print "." }' file |
jq -n -f /dev/stdin

这用于awk创建jq构建数组的表达式。对于给定的示例数据,jq表达式为

."table_name" += ["id"] |
."table_name" += ["col_1"] |
."table_name" += ["col_2"] |
."another_table_name" += ["id"] |
."another_table_name" += ["col_1"] |
.

当通过 求值时jq,这将创建 JSON 文档

{
  "table_name": [
    "id",
    "col_1",
    "col_2"
  ],
  "another_table_name": [
    "id",
    "col_1"
  ]
}

添加-c选项以jq获得紧凑的输出。


使用sed而不是awk

sed -e 's/\([^[:blank:]]*\)[[:blank:]]*\(.*\)/."\1" += ["\2"] |/' \
    -e '$ s/$/./' file |
jq -n -f /dev/stdin

答案2

基本思想是记住上一行的第一个字段,如果相同则打印出逗号,然后打印第二个字段,否则打印第一个和第二个字段。然后处理一些边界情况

awk '$1 == saved { printf(",%s", $2); next ; }
     neednl { print ""; }
     { saved=$1 ; neednl=1 ;printf("%s %s",$1,$2) ; }
     END { if (neednl) { print "" ; }}'

相关内容