【问题标题】:Passing variables between piped awk statements在管道 awk 语句之间传递变量
【发布时间】:2015-08-26 16:44:37
【问题描述】:

我有一个名为 PPR 的打印假脱机系统,它在其他系统之间控制用户打印平衡。命令“ppuser show username”打印给定用户的信息,如下所示。

[root@localhost ~]# ppuser show dpacheco
Name: dpacheco
Fullname: 
Balance: 99.00
Cutoff point: 0.00
Last Modified: Wed Oct  1 11:37:58 2014
Account lifetime: 365
Credit revoked: FALSE

我需要为所有系统用户输出一个“username;balance”对列表(PPR 用户与 /etc/passwd 中列出的相同)。为了实现这一点,我写了这个命令......

cat /etc/passwd | awk -F : '$user=$1 {system("ppuser show "$user)}'| awk '$1 ~ /Balance/ {print $user;$2}'

解释..

  1. 输出passwd的内容。
  2. 将其传递给 awk 语句。
  3. 我获得了用户名,将其存储在 $user var 中并使用它执行“ppuser show”命令。
  4. 将结果传递给另一个 awk 语句
  5. 为包含“余额”的行计算“ppuser show”输出,并打印用户名和余额,用分号分隔。

问题.. 我得到这样的输出

Balance: 100.00;100.00
Balance: -40.00;-40.00
Balance: 100.00;100.00
Balance: 100.00;100.00
Balance: 100.00;100.00
Balance: 100.00;100.00
.
.
.

我看到的是 $user 变量没有在管道之间正确传递。 我做错了什么?

谢谢

【问题讨论】:

  • 只有您输出的内容才会通过管道传递。变量是每个进程的。所以抓住BalanceName 行,并在第二个awk 脚本中按照你想要的方式打印出来。或者在一个 awk 脚本中完成所有操作。

标签: linux bash awk


【解决方案1】:

这里有几个解决方案。

第一个根本不使用 awk。我们使用cut/etc/passwd 中提取用户名,然后使用ppuser 中的grep Balance: 行,使用Gnu grep --label 选项输出用户名:

cut -d: -f1 /etc/passwd | while read -r user; do
  grep -H --label="$user" ^Balance: < <(ppuser show "$user")
done

如果您没有 Gnu grep,您可以使用 printf 以任何方便的格式打印用户名和提取的行:

cut -d: -f1 /etc/passwd | while read -r user; do
  printf "%s: %s\n" "$user" "$(ppuser show "$user" | grep ^Balance:)"
done

如果你愿意,你可以用awk而不是shell来驱动这整个东西,虽然它需要更多的工作(并且没有经过很好的测试,尽管根据@EdMorton的评论我确实修复了一些错别字并验证了它至少适用于一个测试用例)。

awk -F: '{cmd="ppuser show \""$1"\"";
          balance="";
          while ( (cmd | getline balance) > 0) {
            if (balance ~ /^Balance:/) {
              printf "%s:%s\n", $1, substr(balance, index(balance, ":") + 1);
              break;
            }
          }
          close(cmd);
         }' /etc/passwd

【讨论】:

  • 那个 awk 脚本会根据 shell 的$1 的内容和调用getline 的结果产生各种奇怪而奇妙的错误。请参阅 cfajohnson.com/shell/cus-faq-2.html#Q24 了解如何将 shell 变量的值传递给 awk 脚本,并参阅 awk.info/?tip/getline 了解如何/何时使用 getline。您也不需要所有那些尾随分号。
  • @edmorton,哎呀。我不打算从 shell 传递 1 美元。只是在命令行中引用它。将编辑。
  • @edmorton:我改变了我对 getline 的使用以更正确地响应错误,并且括号嵌套以便在正确的位置发生关闭。所以,是的,我应该测试一下。但是我对 getline 的使用与您链接页面中适当使用的示例(a)完全对应。
  • 第一种方法输出Balance: 100.00,第二种方法输出alexcaro: Balance: 100.00。我想我会锻炼第二个,因为它更接近我想要的,只需要摆脱“平衡”部分。谢谢@rici
  • @DagoPacheco:您可以通过cut -f2 -d:sed 's/Balance: //' 进行管道传输(无论您喜欢哪个)。或者你可以使用我修改的 awk 解决方案,只打印: 之后的balance 部分。
猜你喜欢
  • 2021-02-20
  • 1970-01-01
  • 2013-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-17
相关资源
最近更新 更多