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 / 问题 / 791622
Accepted
luator
luator
Asked: 2025-02-25 21:38:28 +0800 CST2025-02-25 21:38:28 +0800 CST 2025-02-25 21:38:28 +0800 CST

对 CSV 文件的每一行运行命令,使用命令不同位置的字段

  • 772

我有一个 CSV 文件,想要对每一行运行一个命令,并使用文件的字段作为单独的参数。

例如给定以下文件:

foo,42,red
bar,13,blue
baz,27,green

我想依次运行以下命令:

my_cmd --arg1 42 --arg2 foo --arg3 red
my_cmd --arg1 13 --arg2 bar --arg3 blue
my_cmd --arg1 27 --arg2 baz --arg3 green

实现此目的的最简单方法是什么?似乎可以使用 xargs 来实现,但我不知道具体如何实现。

shell
  • 5 5 个回答
  • 340 Views

5 个回答

  • Voted
  1. Best Answer
    Marcus Müller
    2025-02-25T22:18:44+08:002025-02-25T22:18:44+08:00

    GNUparallel可以直接读取 csv,并内置了项目替换功能。

    或多或少直接取自man parallel:

    parallel --csv 'my_cmd --arg1 {2} --arg2 {1} --arg3 {3}' :::: file.csv
    

    -j1在这些调用之前添加my_cmd一个接一个地执行。或者不添加,让它们并行执行。

    (在 debian 和 fedora 上,它位于名为 的包中parallel,而不是在moreutils或 中moreutils-parallel)

    谢谢你,Ole Tange!

    • 9
  2. wobtax
    2025-02-25T21:46:42+08:002025-02-25T21:46:42+08:00

    我发现 awk 比 xargs 更容易一些,因此我倾向于使用 awk 组装参数,然后将它们传递给 xargs:

    $ awk -F ',' '{ print "--arg1", $2, "--arg2", $1, "--arg3", $3 }' csv.txt | xargs -L1 echo
    --arg1 42 --arg2 foo --arg3 red
    --arg1 13 --arg2 bar --arg3 blue
    --arg1 27 --arg2 baz --arg3 green
    

    这里-L1说的是“每行输入运行一个命令”。

    • 4
  3. Kusalananda
    2025-02-25T22:03:47+08:002025-02-25T22:03:47+08:00

    下面首先使用 Miller ( mlr) 将无标头 CSV 输入转换为 JSONL 输出(单个 JSON 对象的行)。jq然后 JSON 处理器读取这些对象并将其部分作为参数输出到命令。输出是可以eval-ed 的 shell 代码。

    $ cat file
    foo,42,red
    bar,13,blue
    baz,27,green
    """mute"" swan","1,23",* * green * *
    
    $ mlr --c2l -N cat file
    {"1": "foo", "2": 42, "3": "red"}
    {"1": "bar", "2": 13, "3": "blue"}
    {"1": "baz", "2": 27, "3": "green"}
    {"1": "\"mute\" swan", "2": "1,23", "3": "* * green * *"}
    
    $ mlr --c2l -N cat file | jq -r '["my_cmd", "--arg1", ."1", "--arg2", ."2", "--arg3", ."3"] | @sh'
    'my_cmd' '--arg1' 'foo' '--arg2' 42 '--arg3' 'red'
    'my_cmd' '--arg1' 'bar' '--arg2' 13 '--arg3' 'blue'
    'my_cmd' '--arg1' 'baz' '--arg2' 27 '--arg3' 'green'
    'my_cmd' '--arg1' '"mute" swan' '--arg2' '1,23' '--arg3' '* * green * *'
    

    输出操作符@sh尝试以适合 shell 的方式引用给定的数据。它并非万无一失,但大多数情况下效果不错。

    $ eval "$(mlr --c2l -N cat file | jq -r '["my_cmd", "--arg1", ."1", "--arg2", ."2", "--arg3", ."3"] | @sh')"
    zsh: command not found: my_cmd
    zsh: command not found: my_cmd
    zsh: command not found: my_cmd
    zsh: command not found: my_cmd
    
    $ my_cmd () { echo ""; printf 'arg: %s\n' "$@"; }
    $ eval "$(mlr --c2l -N cat file | jq -r '["my_cmd", "--arg1", ."1", "--arg2", ."2", "--arg3", ."3"] | @sh')"
    
    arg: --arg1
    arg: foo
    arg: --arg2
    arg: 42
    arg: --arg3
    arg: red
    
    arg: --arg1
    arg: bar
    arg: --arg2
    arg: 13
    arg: --arg3
    arg: blue
    
    arg: --arg1
    arg: baz
    arg: --arg2
    arg: 27
    arg: --arg3
    arg: green
    
    arg: --arg1
    arg: "mute" swan
    arg: --arg2
    arg: 1,23
    arg: --arg3
    arg: * * green * *
    

    您也可以直接从 Miller 运行程序,但我不知道它的exec()函数处理需要在 shell 中引用的值的效果如何(或者这是否是个问题)。如果我有时间测试它,我可能会稍后回来修改它。

    • 4
  4. jubilatious1
    2025-02-26T04:56:51+08:002025-02-26T04:56:51+08:00

    使用Raku(以前称为 Perl_6)

    ...使用 RakuText::CSV模块:

    ~$  raku -MText::CSV -e '
    
        my $fh = open "luator.txt", :r;
        my $parser = Text::CSV.new;
    
        until $fh.eof {
              $_ = $parser.getline($fh); 
              run "echo", .[0], .[1], .[2] given $_;
        }
    
        $fh.close;'
    

    Raku 是 Perl 家族中的一种编程语言,具有一些用于调用外部命令的出色功能。两个选项是 调用shell或 调用run。根据文档,调用run更安全。

    上面,当您声明$parser对象时,您可以设置各种参数,例如接受非逗号分隔符(例如my $parser = Text::CSV.new(sep => "|");:)。然后使用逐行读取/解析文件getline()。上面显示了使用的一个简单输出echo。

    示例输入:

    ~$ cat luator.txt
    foo,42,red
    bar,13,blue
    baz,27,green
    

    示例输出(带有echo):

    foo 42 red
    bar 13 blue
    baz 27 green
    

    下面,使用run "printf", "%s\t", .[0].uc, .[1], .[2].uc given $_; run "printf", "\n";,用制表符分隔列输出\t。请注意,这里我们将.uc第一列和第三列改为大写,以表明您仍然可以根据需要清理文本(在调用 之前my_cmd):

    示例输出(带有printf):

    FOO 42  RED
    BAR 13  BLUE
    BAZ 27  GREEN
    

    最后,您可以使用 Raku 的动态变量从命令行中删除输入文件$*ARGFILES。显然,您将替换以下my_cmd内容printf:

    ~$ raku -MText::CSV -e '
             my $parser = Text::CSV.new;    
             until $*ARGFILES.eof {
                   $_ = $parser.getline($*ARGFILES); 
             run "printf", "%s ", "--arg1", .[0], "--arg2", .[1], "--arg3", .[2] given $_;
             run "printf", "\n";
       };'   luator.txt
    --arg1 foo --arg2 42 --arg3 red
    --arg1 bar --arg2 13 --arg3 blue
    --arg1 baz --arg2 27 --arg3 green
    

    否则,请参阅下面的第一个链接,了解如何将输出保存到 Raku“Proc”(进程)对象,或请参阅下面的第二个链接,了解如何使用“Proc::Async”(异步进程接口)。

    https://docs.raku.org/type/Proc
    https://docs.raku.org/type/Proc/Async
    https://raku.org

    • 3
  5. Ed Morton
    2025-02-26T21:17:03+08:002025-02-26T21:17:03+08:00

    将字段选择/排序(f=...见下文)与添加--argN(循环)分开,以便可以轻松修改字段和/或排序,并可能使用 anyawk和 POSIX多次使用相同的字段xargs:

    $ awk -F, -v f='2,1,3' '
        {
            n = split(f, flds)
            for (i = 1; i <= n; i++) {
                printf " --arg%d \"%s\"", i, $(flds[i])
            }
            print ""
        }
    ' file | xargs -L1 echo my_cmd
    my_cmd --arg1 42 --arg2 foo --arg3 red
    my_cmd --arg1 13 --arg2 bar --arg3 blue
    my_cmd --arg1 27 --arg2 baz --arg3 green
    

    测试完成后删除echo。

    鉴于此,更改顺序和复制字段就像更改一样简单f='...':

    $ awk -F, -v f='3,1,3,2,1' '
        {
            n = split(f, flds)
            for (i = 1; i <= n; i++) {
                printf " --arg%d \"%s\"", i, $(flds[i])
            }
            print ""
        }
    ' file | xargs -L1 echo my_cmd
    my_cmd --arg1 red --arg2 foo --arg3 red --arg4 42 --arg5 foo
    my_cmd --arg1 blue --arg2 bar --arg3 blue --arg4 13 --arg5 bar
    my_cmd --arg1 green --arg2 baz --arg3 green --arg4 27 --arg5 baz
    

    \"周围的 s是%s为了确保xargs能够正确处理包含空格的字段,否则像这样的字段a b将被分成 2 个单独的参数my_cmd。

    • 0

相关问题

  • 这个命令是如何工作的?mkfifo /tmp/f; 猫/tmp/f | /bin/sh -i 2>&1 | 数控 -l 1234 > /tmp/f

  • FreeBSD 的 sh:列出函数

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

  • grep -v grep 有什么作用

  • 如何将带有〜的路径保存到变量中?

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