在 Bash 中参数化对实用程序的链式调用

在 Bash 中参数化对实用程序的链式调用

我有一个在 Bash shell 中使用的黑盒 UNIX 程序,它从 stdin 读取数据列,处理它们(应用平滑效果),然后输出到 stdout。我通过 UNIX 管道使用它,例如

generate | smooth | plot  

为了更加平滑,我可以重复平滑,因此可以从 Bash 命令行调用它

generate | smooth | smooth | plot   

甚至

generate | smooth | smooth | smooth | smooth | smooth | smooth | smooth | smooth | smooth | smooth | plot

这变得不舒服了。我想制作一个 Bash 包装器,以便能够smooth将其输出通过管道输入smooth任意次数的新实例,例如

generate | newsmooth 5 | plot

代替

generate | smooth | smooth | smooth | smooth | smooth | plot

我的第一次尝试是使用 Bash 脚本在当前目录中生成临时文件并删除它们,但是当我不在具有写访问权限的目录中时,它会变得很难看,并且在中断时还会留下垃圾文件。

该程序没有任何参数smooth

有没有更优雅的方法来“包装”这样的程序来参数化调用次数?

答案1

您可以将其包装在递归函数中:

smooth() {
  if [[ $1 -gt 1 ]]; then # add another call to function
    command smooth | smooth $(($1 - 1)) 
  else
    command smooth # no further 
  fi
}

你可以用它作为

generate | smooth 5 | plot

这相当于

generate | smooth | smooth | smooth | smooth | smooth | plot

答案2

如果您可以输入与所需命令数量一样多的逗号smooth,则可以利用 shell 的逗号分隔大括号扩展。

TL; DR

您的示例案例的整个命令行将是:

generate | eval 'smooth |'{,,,,} plot

笔记:

  • 如果您想要更多或更少的重复,请添加或删除逗号smooth |
  • 没有|beforeplot因为它包含在smooth |大括号扩展生成的最后一个字符串中
  • 您还可以向 提供参数smooth,只要您可以将它们正确地包含在左大括号之前的带引号的固定部分中即可;无论如何请记住,您将把它们提供给全部重复命令

怎么运行的

逗号分隔的大括号扩展允许您动态生成字符串,每个字符串由指定的固定部分加上指定的可变部分组成。它会生成与指示的可变部分一样多的字符串,例如a{b,c,d}Produce ab ac ad

这里的小技巧是,如果你想列出一个清单空的可变部分,即大括号内只有逗号,大括号扩展将仅生成固定部分的副本。例如:

smooth{,,,,}

将产生:

smooth smooth smooth smooth smooth

注意4逗号产生 5 个smooth字符串。这就是大括号扩展的工作原理:它生成与逗号加一一样多的字符串。

当然,在您的情况下,您还需要一个|分隔的 every smooth,因此只需将其添加到固定部分,但请注意正确引用它以获得 shell不是立即解释它。那是:

'smooth|'{,,,,}

将产生:

'smooth|' 'smooth|' 'smooth|' 'smooth|' 'smooth|'

注意始终放置固定部分立即地与左大括号相邻,即' 和之间没有空格{

(另请注意,如果需要在固定部分中扩展 shell 变量,则为了形成固定部分,您也可以使用双引号而不是单引号。只需注意出现某些 shell 特殊字符时所需的额外转义即可在双引号字符串内)。

此时,您需要将该eval 字符串应用于该字符串,以使 shell 最终将其解释为它应该是的管道命令。

因此,总而言之,示例案例的整个命令行将是:

generate | eval 'smooth |'{,,,,} plot

相关内容