【问题标题】:Appending result of function on another field into csv using shell script, awk使用 shell 脚本 awk 将另一个字段上的函数结果附加到 csv 中
【发布时间】:2019-01-29 00:57:39
【问题描述】:

我有一个 csv 文件作为临时变量存储在 shell 脚本 (*.sh) 中。

假设数据如下所示:

Account,Symbol,Price
100,AAPL US,200
102,SPY US,500

我想添加第四列“Type”,它是 shell 函数“foobar”的结果。从命令行或 shell 脚本本身运行:

$ foobar "AAPL US"
"Stock"
$ foobar "SPY US"
"ETF"

如何将此列添加到我的 csv 中,并通过调用以第二列作为参数的 foobar 来填充它?澄清一下,这是我理想的结果后记:

Account,Symbol,Price,Type
100,AAPL US,200,Common Stock
102,SPY US,500,ETF

我在网上看到很多例子,涉及使用 awk 添加这样的列,并使用固定值、条件值、来自其他列的数学推导等填充新列 - 但没有在另一个字段上调用函数并存储其输出.

【问题讨论】:

    标签: shell csv awk sed edit


    【解决方案1】:

    你可以使用这个awk:

    export -f foobar
    
    awk 'BEGIN{FS=OFS=","} NR==1{print $0, "Type"; next} {
       cmd = "foobar \"" $2 "\""; cmd | getline line; close(cmd); 
       print $0, line
    }' file.csv
    

    Account,Symbol,Price,Type
    100,AAPL US,200,Common Stock
    102,SPY US,500,ETF
    

    【讨论】:

    • 谢谢!这行得通。将该字段附加到 csv 中。
    • 我收到sh: 1: foobar: not found,知道为什么以及如何使它工作吗? :O
    • 我创建了一个包含一些虚拟函数 foobar() { echo foo; } 的脚本,然后简单地复制粘贴了您的代码。
    • @anubhava bash: foobar: command not found ...太奇怪了。我会尝试更深入地研究它:) 感谢您的帮助。
    • 请参阅 stackoverflow.com/a/51978440/1745001 以获取我无法在评论中添加的反馈。
    【解决方案2】:

    @anubhavas 答案是一个好方法,因此请不要更改已接受的答案,因为我只是将其作为答案发布,因为它太大并且需要格式化以适应评论。

    FWIW 我会把他的 awk 脚本写成:

    awk '
        BEGIN { FS=OFS="," }
        NR==1 { type = "Type" }
        NR > 1 {
            cmd  = "foobar \047" $2 "\047"
            type = ((cmd | getline line) > 0 ? line : "ERROR")
            close(cmd)
        }
        { print $0, type }
    ' file.csv
    

    到:

    1. 更好地保护 $2 免受 shell 扩展,并且
    2. 如果/当cmd | getline 失败时,防止静默打印先前的值,并且
    3. 将打印语句合并为 1 行,以便在必要时/在必要时轻松更改所有输出行

    【讨论】:

      【解决方案3】:

      awk 来救援!

      $ echo "Account,Symbol,Price
      100,AAPL US,200
      102,SPY US,500" | 
      awk -F, 'NR>1{cmd="foobar "$2; cmd | getline type} {print $0 FS (NR==1?"Type":type)}'
      

      不确定是否需要将输入引用到foobar

      【讨论】:

        【解决方案4】:

        不使用awk的另一种方式:

        paste -d, input.csv <({ read; printf "Type\n"; while IFS=, read -r _ s _; do foobar "$s"; done; } < input.csv)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-07-21
          • 1970-01-01
          • 2012-03-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多