Как трубу на условии в Баш - PullRequest
1 голос
/ 03 июля 2019

Я чрезмерно усложняю проблему, но есть ли способ передать команду в другую, учитывая условие на одну строку в 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" будет передано в буфер обмена, иначе содержимое будет выведено в стандартный вывод, и канал никогда не активируется, и ничего не записывается в буфер обмена. Я хочу, чтобы это был однострочник, когда я вызываю эхо только один раз.

Ответы [ 4 ]

3 голосов
/ 03 июля 2019
$ 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
0 голосов
/ 03 июля 2019

Условно определенная функция может быть более подходящей в некоторых случаях, например, если check проверяется много.Это также предполагает, что значение check не изменится между использованиями receiver.

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

printf 'foo' | receiver
0 голосов
/ 03 июля 2019

Используйте специальную переменную (возможно 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 голосов
/ 03 июля 2019

Вы не так далеко.

Вы можете направить свой вывод echo в субоболочку

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

В этом коде будет использоваться ваш echoв качестве ввода либо xclip, либо cat в зависимости от условия.

Редактировать:

Если вы также хотите, чтобы команда потерпела неудачу, если 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>&-
...