我有一个场景需要取消数据透视以实现父子关系。我的源数据如下:
Key_Col|层次结构
1|a,b,c,d
2|a,b,c,d,e
我的预期输出如下:
键列 | 孩子 | 家长 |
---|---|---|
1个 | d | C |
1个 | C | b |
1个 | b | A |
1个 | A | 无效的 |
2个 | 电子 | d |
2个 | d | C |
2个 | C | b |
2个 | b | A |
2个 | A | 无效的 |
您能否告诉我如何通过 bash 脚本实现此目的?
我使用的脚本是:
Var="1|a,b,c,d";
for i in $Var
do
Key=`echo $i |cut -d'|' -f1`
Hierarchy=`echo $i |cut -d'|' -f2`
Delim_Count=`echo ${Hierarchy} |awk -F',' '{ print NF-1 }'`
for (( c=$Delim_Count+1; c>=1; c-- ))
do
Parent=`echo ${Hierarchy} |cut -d',' -f$c`
Prev=`expr $c - 1`
if [ $Prev -ne 0 ]; then
Child=`echo ${Hierarchy} |cut -d',' -f${Prev}`
echo "${Key}|${Parent}|${Child}"
else
echo "${Key}|${Parent}|"
fi
done
done
但问题是,如果超过 100 行,脚本就需要很长时间才能完成。
使用用于处理文本或结构化数据的语言通常更容易做这些事情。下面是一个使用标准文本处理实用程序的解决方案
awk
和一个使用Miller (mlr
) 的解决方案,这是一种专门用于处理结构化数据(您的数据看起来像 CSV)的工具。与
awk
:上面的代码
awk
将每个输入行读取为一组|
-delimited 字段。它将逗号上的第二个字段拆分为数组a
。数组的第零个元素设置为字符串null
(split()
创建一个第一个索引为 1 的数组,因此我们知道我们可以使用索引 0 而不会覆盖数据)。然后我们从数组的末尾迭代到开头,输出第一个字段的值以及当前数组元素和数组中的前一个元素。当我们到达最后一次迭代时,我们的循环变量的值为 1,这会导致打印a[1]
anda[0]
( )。null
包含标题的第一行输入被区别对待。代码没有拆分等,而是打印了三个字段:来自输入的第一个字段和一个字段,每个字段用于字符串
Child
和Parent
。条件NR==1
块执行此操作。为便于阅读而重新格式化的代码
awk
:由于输入看起来像 CSV,因此使用支持 CSV 的工具来处理它可能更安全。米勒 (
mlr
) 就是这样一个工具:Miller
put
表达式遵循与上述代码相同的大纲awk
,但不必将标头作为特殊情况处理,因为 Miller 知道如何阅读和使用这些标头:put
Miller 允许我们通过调整子命令之前的选项来产生多种不同形式的结果。漂亮的“禁止”输出:
JSON:
(ETC。)