【问题标题】:Bash shell scripting , how to use pipes in commandBash shell 脚本,如何在命令中使用管道
【发布时间】:2021-06-12 13:26:55
【问题描述】:

尝试在 bash 脚本中使用管道。这在我的 Linux shell 上运行良好,但 bash 脚本出错了。我做错了什么?

  #!/bin/bash
  #some code
  cmd="cat file2 | grep ':'  | awk -F \":\" '{print \$1}' > pool_names"
  echo $cmd
  exec $cmd
 

我看到了这个错误

cat: invalid option -- 'F'
Try 'cat --help' for more information.

【问题讨论】:

  • 它不是这样工作的——你需要使用eval "$cmd" 将管道评估为管道而不是字符串,但是使用eval 是非常危险的。您也可以使用bash -c "$cmd",但这相当于eval。我保留在eval "$cmd" 中使用引号错误的权利(也许应该是eval $cmd),但使用eval 仍然不安全。
  • 澄清一下,您正在调用 cat,参数为 file2|grep:|awk-F 等。 cat 将前 6 个参数视为文件名(或者,如果它达到那么远,它会),但不将 -F 识别为有效选项,因此它正在中止。
  • 你很幸运; cat | grep | awk 是一种反模式,您可以轻松地完全避开管道。

标签: linux bash shell pipe


【解决方案1】:

bash 内置exec 命令有一个完全不同的目标,如https://www.computerhope.com/unix/bash/exec.htm 所述。

您必须将 exec 替换为 eval 才能使您的脚本正常工作,或者作为替代方案,正如 @Jonathan Leffler 在评论中所建议的那样,您可以使用 bash -c "$cmd"

【讨论】:

    【解决方案2】:

    在 shell 中,“简单命令”是一系列可选的变量赋值和重定向,以任意顺序,可选地后跟单词和重定向,由控制运算符终止。 (参见https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_09_01),而管道是由控制运算符“|”分隔的一个或多个命令的序列(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_09_02)。当外壳程序看到exec $cmd 行时,它看不到控制运算符|,所以这是一个简单的命令。 (这与exec 无关,任何命令都会发生相同的行为。)然后它扩展行中的变量并遵循规则the first field shall be considered the command name and remaining fields are the arguments for the command,因此exec 被调用时带有一堆参数。 exec 不会尝试将参数解释为 shell 运算符(也许您打算使用 eval 而不是 exec),而只是将所有参数传递给 cat

    【讨论】:

      猜你喜欢
      • 2019-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-27
      • 2012-08-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多