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 / 问题 / 707563
Accepted
Aayush Jain
Aayush Jain
Asked: 2022-06-26 22:35:03 +0800 CST2022-06-26 22:35:03 +0800 CST 2022-06-26 22:35:03 +0800 CST

将多行汇总为单行

  • 772

如何将 csv 文件中的多行汇总为 1 行?我已经尝试在 SQL 中进行查询并且它可以工作,但我不确定如何在 Linux 中实现相同的效果。

这是我当前文件的外观:

swainb02,Ben Swain,1015
swainb02,Ben Swain,1016
swainb02,Ben Swain,1018
swainb02,Ben Swain,1020
shaiks21,Sarah Shaikh,0073
shaiks21,Sarah Shaikh,0080
shaiks21,Sarah Shaikh,0082

有多个用户可以访问多个区号。我正在寻找的是该文件的更简单版本,以提高可读性。

期望的输出:

swainb02,Ben Swain,1015,1016,1018,1020
shaiks21,Sarah Shaikh,0073,0080,0082

知道如何解决吗?谢谢

linux csv-simple
  • 5 5 个回答
  • 64 Views

5 个回答

  • Voted
  1. RudiC
    2022-06-27T02:49:44+08:002022-06-27T02:49:44+08:00

    在结果上运行一个小awk脚本:

    awk -F, '
    $1$2 != Last    {printf DL "%s", $0
                     Last=$1$2
                     DL=ORS
                     next
                    }
                    {printf ",%s", $3
                    }
    END             {print ""
                    }
    ' file
    swainb02,Ben Swain,1015,1016,1018,1020
    shaiks21,Sarah Shaikh,0073,0080,0082
    

    它打印一次新用户的数据,然后附加区号,直到遇到下一个用户。

    • 1
  2. Kusalananda
    2022-06-27T04:32:28+08:002022-06-27T04:32:28+08:00

    假设输入是没有嵌入逗号、换行符或引号的简单 CSV,我们可以使用 GNUdatamash按前两个逗号分隔的字段分组并折叠第三个字段:

    $ datamash -t, groupby 1,2 collapse 3 <file
    swainb02,Ben Swain,1015,1016,1018,1020
    shaiks21,Sarah Shaikh,0073,0080,0082
    

    这假定数据在前两个字段上排序(或者将一起排序的记录在文件中彼此相邻,如示例数据中所示)。如果不是,则sort -t, -k 1,2首先传递数据,或使用datamash其-s(or --sort) 选项。

    • 1
  3. Best Answer
    Ed Morton
    2022-07-02T02:33:28+08:002022-07-02T02:33:28+08:00

    假设您的输入按问题中所示的键值分组(如果不只是先对输入进行排序)然后在每个 Unix 机器上的任何 shell 中使用任何 awk 并且无论您的输入文件有多大,都几乎不使用内存:

    $ cat tst.awk
    BEGIN { FS=OFS="," }
    { curr = $1 OFS $2 }
    curr != prev {
        printf "%s%s", ors, curr
        prev = curr
        ors = ORS
    }
    { printf "%s%s", OFS, $3 }
    END { printf ors }
    

    $ awk -f tst.awk file
    swainb02,Ben Swain,1015,1016,1018,1020
    shaiks21,Sarah Shaikh,0073,0080,0082
    
    • 1
  4. Marcus Müller
    2022-06-27T02:18:57+08:002022-06-27T02:18:57+08:00

    我已经尝试在 SQL 中计算查询并且它有效

    伟大的。然后在sqlite :memory:没有文件支持数据库的情况下运行工作(假设没有数十亿行,这应该没问题)。在那里,运行(或只是将此程序通过管道传输到解释器中)

    .mode csv
    .import yourfile.csv users
    SELECT … FROM users …; # this is the SQL query that already works!
    

    完毕。该sqlite3客户端几乎在任何地方都可用,我将其称为最类似于 UNIX 的方法,它使用结构化查询语言解释器来执行这样的结构化查询。总而言之,你可以在你的 shell 中输入这个(bash/dash/zsh 和类似的):

    function runmyquery() {
    sql="
    .mode csv
    .import $1 users
    SELECT … FROM users …; # replace with your query!
    "
    echo "${sql}" | sqlite3 :memory: 
    }
    

    之后,您可以运行runmyquery myfile.csv并获得结果。sqlite3也可以交互使用。

    • 0
  5. r_31415
    2022-06-27T14:06:31+08:002022-06-27T14:06:31+08:00

    无论行的顺序如何,这个 awk 版本都可以工作:

    {
      if ($1 "," $2 in a) {
        a[$1 "," $2] = a[$1 "," $2] "," $3
      } else {
        a[$1 "," $2] = $3
      }
    }
    
    END {
      for (i in a) {
        print i, a[i]
      }
    }
    
    

    另一方面,csvkit 输出更正确的结果:

    csvsql -H -d ',' --query 'SELECT a,b, GROUP_CONCAT(c) as c FROM data GROUP BY a, b' data.txt
    a,b,c
    shaiks21,Sarah Shaikh,"73.0,80.0,82.0"
    swainb02,Ben Swain,"1015.0,1016.0,1018.0,1020.0"
    

    尽管没有引号看起来更好,但另一个示例很容易导致每行的字段数量不同。对于进一步处理,非常需要具有分隔的第三字段的输出。

    • 0

相关问题

  • 有没有办法让 ls 只显示某些目录的隐藏文件?

  • 使用键盘快捷键启动/停止 systemd 服务 [关闭]

  • 需要一些系统调用

  • astyle 不会更改源文件格式

  • 通过标签将根文件系统传递给linux内核

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