【问题标题】:How to pipe on a condition in Bash如何在 Bash 中对条件进行管道传输
【发布时间】:2019-07-03 12:45:38
【问题描述】:

我的问题过于复杂了,但是有没有办法在 Bash 中给定单行条件时将命令传递到另一个命令?

基本上我现在有这个

if [ "$check" -eq 1 ]; then
    echo -n "foo" | xclip -selection clipboard
else
    echo -n "foo"
fi

我想知道在 Bash 中是否有将它变成如下所示的东西:

echo -n "foo" && [ "$check" -eq 1 ] | xclip -selection clipboard

如果 $check == 1,“foo”将通过管道传输到剪贴板,否则内容将输出到标准输出,管道永远不会激活,也不会将任何内容写入剪贴板。我希望这是一个单行,我只调用一次 echo。

【问题讨论】:

    标签: bash scripting pipe


    【解决方案1】:
    $ check=0
    $ echo "foo" | { if (( check == 1 )); then cat -n; else cat -; fi; }
    foo
    
    $ check=1
    $ echo "foo" | { if (( check == 1 )); then cat -n; else cat -; fi; }
         1  foo
    

    【讨论】:

    • 如果将cat -n 更改为剪贴板,这将非常有效。感谢一百万埃德。
    • 不客气。有问题的命令是clipboard 还是cat -n 或其他一些采用管道输入的命令对于如何有条件地管道到命令的问题并不重要,并不是每个人的系统上都有clipboard,所以使用@987654326对于这个论坛的读者来说,@ 这个例子通常比使用 clipboard 更有用,因为每个人都可以复制/粘贴我的答案来尝试它。
    【解决方案2】:

    为您的可选命令使用一个特殊的变量(可能是check,我将使用cmd)(例如大写):

    # default
    cmd='cat -'
    echo "foo" | $cmd
    # output: foo
    cmd='tr [:lower:] [:upper:]'
    echo "foo" | $cmd
    # output FOO
    

    当您希望此构造具有不断变化的 check 值时,您可以使用函数:

    xcmd() {
       sed '/0/ s/.*/cat -/; /1/ s/.*/tr [:lower:] [:upper:]/' <<< "${check-0}"
    }
    

    xclip

    xcmd() {
       sed '/0/ s/.*/cat -/; /1/ s/.*/xclip -selection clipboard/' <<< "${check-0}"
    }
    

    现在:

    check=0
    echo "foo" | $(xcmd)
    # output: foo
    check=1
    echo "foo" | $(xcmd)
    # output: FOO or the xclip pipe
    

    【讨论】:

      【解决方案3】:

      条件定义的函数在某些情况下可能更合适,例如如果check 被大量检查。这还假设check 的值在receiver 的使用之间不会改变。

      if (( check == 1 )); then
          receiver () {
              xclip -selection clipboard
          }
      else
          receiver () {
              cat -n
          }
      fi
      
      printf 'foo' | receiver
      

      【讨论】:

        【解决方案4】:

        你并不遥远。

        您可以将echo 的输出通过管道传输到子shell

        echo -n "foo" | ([[ "$check" -eq 1 ]] && xclip -selection clipboard || cat - )
        

        在此代码中,您的echo 将根据条件被xclipcat 用作输入。

        编辑:

        如果您还希望命令在xclip 失败时失败,您可以执行以下操作:

        echo -n "foo" | ( ( [[ "$check" -ne 1 ]] && cat - ) || ( [[ "$check" -eq 1 ]] && xclip -selection clipboard ) )
        

        但这种方式可能比你的多行代码可读性差。

        只有一个echo 的多行解决方案可以是:

        # Create temporary pipe file
        PIPE=$(mktemp -u)
        mkfifo $PIPE
        # Open pipe handles
        # 6 can be replaced by any other non-opened fd identifier
        exec 6<>$PIPE
        # Remove file from disk
        rm $PIPE
        echo -n "foo" >&6
        if [[ "$check" -eq 1 ]]; then
            xclip -selection clipboard <&6
        else
            cat - <&6
        fi
        # Close file handles
        exec 6<&- 6>&-
        

        【讨论】:

        • 这并不意味着它看起来意味着什么,它不是一个三元表达式,它只是从左到右评估最后一个运行命令的成功/失败退出状态。如果$check1 并且xclip 失败(或找不到),则将调用cat
        • 这正是我一直在寻找的,尽管正如 Ed 所提到的,如果 xclip 未找到或失败,我理想情况下希望它失败。如果你能解决这个问题,我很乐意给你接受的答案。
        猜你喜欢
        • 2015-01-07
        • 1970-01-01
        • 1970-01-01
        • 2012-05-11
        • 2019-07-30
        • 2010-11-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多