【问题标题】:Conditional pipelining in BashBash 中的条件流水线
【发布时间】:2017-08-15 09:30:34
【问题描述】:

我有一个过滤器,我想选择启用它,我想知道如何在 bash 中以一种干净的方式做到这一点。

FILTER="| sort" # also can be empty
ls $FILTER | cat

此代码不起作用,因为它将以|sort 作为参数调用ls

我怎样才能正确地做到这一点?请注意,我试图避免创建 if 块,以使代码易于维护(我的管道链比此示例复杂得多)

【问题讨论】:

  • 这些过滤器会接收任何类型的参数吗?
  • 一种危险的生活方式是使用eval。如果您完全控制所评估的字符串,那将是安全的;如果用户可以为被评估的字符串提供输入,那将是一场等待发生的灾难。在您期望他们说cat 的地方,也许他们说cat; mv $HOME/.profile $HOME/.junk 或更可怕的东西(并且可能是不可逆转的,或者至少是不可逆转的)。因此,使用eval 是危险的。尽管如此,它还是存在的,而且很有用。

标签: bash pipe


【解决方案1】:

您的想法不起作用,因为变量扩展发生在语法被解析之后。

你可以这样做:

foo_cmd | if [ "$order" = "desc" ] ; then
    sort -r
else
    sort
fi | if [ "$cut" = "on" ] ; then
    cut -f1
else
    cat
fi

【讨论】:

    【解决方案2】:

    您可以创建命令并在不同的 shell 中执行它。

    FILTER="| sort" # create your filter here
    # ls $FILTER | cat  <-- this won't work
    bash -c "ls $FILTER | cat"
    
    # or create the entire command and execute (which, i think, is more clean)
    cmd="ls $FILTER | cat"
    bash -c "$cmd"
    

    如果您选择这种方法,您必须确保命令在语法上有效并且完全按照您的意图执行,而不是做一些灾难性的事情。

    【讨论】:

    • 这会带来动态代码执行的所有缺点,应该避免。
    • @hek2mgl 我同意,但据我了解,OP 正试图通过应用在变量中定义的过滤器来做同样的事情,但不愿意使用条件构造。他必须通过其他方式确保命令有效。
    猜你喜欢
    • 1970-01-01
    • 2020-11-07
    • 2018-02-01
    • 2013-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-04
    相关资源
    最近更新 更多