假设我有如下数据:
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 "" ; }}'