AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 736407
Accepted
MAK33
MAK33
Asked: 2023-02-22 08:15:37 +0800 CST2023-02-22 08:15:37 +0800 CST 2023-02-22 08:15:37 +0800 CST

Unpivoting Delimited String 获取父子关系

  • 772

我有一个场景需要取消数据透视以实现父子关系。我的源数据如下:

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 行,脚本就需要很长时间才能完成。

bash
  • 1 1 个回答
  • 60 Views

1 个回答

  • Voted
  1. Best Answer
    Kusalananda
    2023-02-23T17:40:38+08:002023-02-23T17:40:38+08:00

    使用用于处理文本或结构化数据的语言通常更容易做这些事情。下面是一个使用标准文本处理实用程序的解决方案awk和一个使用Miller ( mlr) 的解决方案,这是一种专门用于处理结构化数据(您的数据看起来像 CSV)的工具。


    与awk:

    $ cat file
    Key_Col|Hierarchy
    1|a,b,c,d
    2|a,b,c,d,e
    
    $ awk 'BEGIN { OFS=FS="|" } NR == 1 { print $1, "Child", "Parent"; next } { n=split($2,a,","); a[0]="null"; for (i=n;i>0;i--) print $1,a[i],a[i-1] }' file
    Key_Col|Child|Parent
    1|d|c
    1|c|b
    1|b|a
    1|a|null
    2|e|d
    2|d|c
    2|c|b
    2|b|a
    2|a|null
    

    上面的代码awk将每个输入行读取为一组|-delimited 字段。它将逗号上的第二个字段拆分为数组a。数组的第零个元素设置为字符串null(split()创建一个第一个索引为 1 的数组,因此我们知道我们可以使用索引 0 而不会覆盖数据)。然后我们从数组的末尾迭代到开头,输出第一个字段的值以及当前数组元素和数组中的前一个元素。当我们到达最后一次迭代时,我们的循环变量的值为 1,这会导致打印a[1]and a[0]( )。null

    包含标题的第一行输入被区别对待。代码没有拆分等,而是打印了三个字段:来自输入的第一个字段和一个字段,每个字段用于字符串Child和Parent。条件NR==1块执行此操作。

    为便于阅读而重新格式化的代码awk:

    BEGIN {
        OFS = FS = "|"
    }
    
    NR == 1 {
        print $1, "Child", "Parent"
        next
    }
    
    {
        n = split($2, a, ",")
        a[0] = "null"
        for (i = n; i > 0; i--)
            print $1, a[i], a[i-1]
    }
    

    由于输入看起来像 CSV,因此使用支持 CSV 的工具来处理它可能更安全。米勒 ( mlr) 就是这样一个工具:

    $ mlr --csv --fs pipe put -q 'm=splitnv($Hierarchy,","); m[0]="null"; for (var i=length(m)-1;i>0;i-=1) { emit {"Key_Col": $Key_Col, "Child": m[i], "Parent": m[i-1] } }' file
    Key_Col|Child|Parent
    1|d|c
    1|c|b
    1|b|a
    1|a|null
    2|e|d
    2|d|c
    2|c|b
    2|b|a
    2|a|null
    

    Millerput表达式遵循与上述代码相同的大纲awk,但不必将标头作为特殊情况处理,因为 Miller 知道如何阅读和使用这些标头:

    m = splitnv($Hierarchy, ",")
    m[0] = "null"
    
    for (var i = length(m) - 1; i > 0; i -= 1) {
        emit {
            "Key_Col": $Key_Col,
            "Child": m[i],
            "Parent": m[i-1]
        }
    }
    

    putMiller 允许我们通过调整子命令之前的选项来产生多种不同形式的结果。

    漂亮的“禁止”输出:

    $ mlr --c2p --barred --ifs pipe put ...as above...
    +---------+-------+--------+
    | Key_Col | Child | Parent |
    +---------+-------+--------+
    | 1       | d     | c      |
    | 1       | c     | b      |
    | 1       | b     | a      |
    | 1       | a     | null   |
    | 2       | e     | d      |
    | 2       | d     | c      |
    | 2       | c     | b      |
    | 2       | b     | a      |
    | 2       | a     | null   |
    +---------+-------+--------+
    

    JSON:

    $ mlr --c2j --ifs pipe put ...as above...
    { "Key_Col": 1, "Child": "d", "Parent": "c" }
    { "Key_Col": 1, "Child": "c", "Parent": "b" }
    { "Key_Col": 1, "Child": "b", "Parent": "a" }
    { "Key_Col": 1, "Child": "a", "Parent": "null" }
    { "Key_Col": 2, "Child": "e", "Parent": "d" }
    { "Key_Col": 2, "Child": "d", "Parent": "c" }
    { "Key_Col": 2, "Child": "c", "Parent": "b" }
    { "Key_Col": 2, "Child": "b", "Parent": "a" }
    { "Key_Col": 2, "Child": "a", "Parent": "null" }
    

    (ETC。)

    • 1

相关问题

  • 通过命令的标准输出以编程方式导出环境变量[重复]

  • 从文本文件传递变量的奇怪问题

  • 虽然行读取保持转义空间?

  • `tee` 和 `bash` 进程替换顺序

  • 运行一个非常慢的脚本直到它成功

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve