如何在 Bash 中使用管道进行条件筛选

5
我可能过于复杂化这个问题,但在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"导入剪贴板,否则将内容输出到stdout并且管道不会激活,也不会写入剪贴板。我希望这是一个只调用echo一次的单行代码。
4个回答

8
$ 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

1
如果将 cat -n 更改为剪贴板,则此功能完美运行。非常感谢,Ed。 - szybia
5
不用谢。无论涉及的命令是 clipboard 还是 cat -n 或者其他接受管道输入的命令,都与有条件地将输出传递给命令的问题无关。而且,并非所有人的系统都安装有 clipboard,因此,在本论坛中使用 cat -n 作为示例比使用 clipboard 更有普适性,因为每个人都可以拷贝/粘贴我的答案来尝试。 - Ed Morton

0

使用一个特殊的变量(也许是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

0
有时候,有条件定义的函数可能更加适合,比如当 check 被频繁检查时。这也假设了在使用 receiver 期间,check 的值不会发生改变。
if (( check == 1 )); then
    receiver () {
        xclip -selection clipboard
    }
else
    receiver () {
        cat -n
    }
fi

printf 'foo' | receiver

0

你离目标并不遥远。

你可以将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>&-

1
这并不意味着它看起来的意思,它不是一个三元表达式,而只是对最后一个运行的命令的成功/失败退出状态进行从左到右的评估。如果 $check1 并且 xclip 失败(或找不到),那么将调用 cat - Ed Morton
这正是我在寻找的,不过正如 Ed 所提到的,如果找不到或失败了,最好能让它失败。如果你能解决这个问题,我会很乐意接受你的答案。 - szybia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接