【问题标题】:How do you process multiple fields running through a pipe?您如何处理通过管道运行的多个字段?
【发布时间】:2017-07-20 18:16:05
【问题描述】:

如果我有一个制表符分隔的数据文件 input.dat,其格式如下:

#id  acct    name   city          age
 12  100290  Sally  San Francisco 24
 15  102911  Jerry  Sacramento    40
 99  102134  Amir   Eureka        82

当数据通过管道时,我可以使用cut(1) 或类似的东西来运行多个处理功能,例如:(lookup_id, scrub_acct, scrub_name, lookup_city, scrub_age) 每个字段吗?

使用一个字段很容易做到这一点:

cat input.dat | cut -f1 | lookup_id > output.dat

但我想知道是否有办法按字段执行此操作,并将结果重定向到 output.dat

#id  acct    name   city          age
 AA  XXXXX0  SXXXX  city-57       20s
 AC  XXXXX1  JXXXX  city-29       40s
 AF  XXXXX4  AXXXX  city-100      80s

也许一个预先问题是你能(简单地做到这一点)吗?

我也在考虑paste(1) 是否可以替代将列粘在一起,但也许有更好的方法。

【问题讨论】:

  • 我建议看看awk
  • 好点,我想你可以在每个字段上运行一个函数并启动一个子shell。有没有办法用 cut 做到这一点? awk 有时就是这样的野兽。 @赛勒斯
  • 那么lookup_id, scrub_acct, scrub_name, lookup_city, scrub_age是shell函数吗?
  • 其中一些可能是,其他可能正在执行 api 调用或数据库查询。 @anubhava
  • 你的问题很不清楚! lookup_idscrub_acct等应该做什么,它们应该取什么参数?

标签: bash pipe cut io-redirection


【解决方案1】:

通常在awk 中处理行、列数据更容易,但由于涉及到 shell 函数,最好在 shell 本身中处理。

假设 lookup_id, scrub_acct, scrub_name, lookup_city, scrub_age 是从标准输入读取输入的 shell 函数或脚本,您可以创建它们的数组并在循环输入文件中的每条记录时调用它们:

# example shell functions
lookup_id() { read str; printf "lookup_id: %s\n" "$str"; }
scrub_acct() { read str; printf "scrub_acct: %s\n" "$str"; }
scrub_name() { read str; printf "scrub_name: %s\n" "$str"; }
lookup_city() { read str; printf "lookup_city: %s\n" "$str"; }
scrub_age() { read str; printf "scrub_age: %s\n" "$str"; }    

# array of functions or scripts to be invoked
fnarr=(lookup_id scrub_acct scrub_name lookup_city scrub_age)

# main processing
while IFS=$'\t' read -ra ary; do
   for ((i=0; i<${#ary[@]}; i++)); do
      # call function for each field value
      "${fnarr[i]}" <<< "${ary[i]}"
   done
   echo '============================='
done < <(tail -n +2 file)

输出:

lookup_id: 12
scrub_acct: 100290
scrub_name: Sally
lookup_city: San Francisco
scrub_age: 24
=============================
lookup_id: 15
scrub_acct: 102911
scrub_name: Jerry
lookup_city: Sacramento
scrub_age: 40
=============================
lookup_id: 99
scrub_acct: 102134
scrub_name: Amir
lookup_city: Eureka
scrub_age: 82
=============================

【讨论】:

  • 变量替换,很聪明。您将其用作一种调度程序,感谢您的想法!
  • "${fnarr[i]}" &lt;&lt;&lt; "${ary[i]}",效率更高?
【解决方案2】:

用 awk 试试这样的东西:

awk -F'\t' '{system("lookup_id "  $1); printf("\t"); \
             system("scrub_acct " $2); printf("\t"); \
             ...
            }' input.dat

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-23
    • 1970-01-01
    • 2021-05-01
    • 2018-02-02
    • 1970-01-01
    相关资源
    最近更新 更多