다음과 같은 파이프라인이 있다고 가정해 보겠습니다.
cmd1 < input.txt |\
cmd2 |\
cmd4 |\
cmd5 |\
cmd6 |\
(...) |\
cmdN > result.txt
어떤 경우에는 과 사이에 을 추가하고 싶습니다 cmd3
. 결과를 임시 파일에 저장하지 않고 일종의 조건부 파이프라인을 생성하는 방법이 있습니까? 나는 다음과 같은 것을 생각할 것입니다 :cmd2
cmd4
cmd2
cmd1 < input.txt |\
cmd2 |\
(${DEFINED}? cmd3 : cat ) |\
cmd4 |\
cmd5 |\
cmd6 |\
(...) |\
cmdN > result.txt
답변1
일반적인 &&
AND ||
연산자:
cmd1 < input.txt |
cmd2 |
( [ -n "$DEFINED" ] && cmd3 || cat ) |
cmd4 |
cmd5 |
cmd6 |
(...) |
cmdN > result.txt
비록 명시된 대로이 답변if ... else
, if-else 구문을 사용하는 경우 일반적으로 선호합니다.
...
cmd2 |
if [ -n "$DEFINED" ]; then cmd3; else cat; fi |
cmd4 |
...
(줄이 파이프로 끝나면 후행 백슬래시가 필요하지 않습니다.)
고쳐 쓰다~에 따르면요나스의 관찰. cmd3이 0이 아닌 종료 코드로 종료될 수 있고 나머지 입력을 처리
하지 않으려면 논리를 반대로 바꾸세요.cat
cmd1 < input.txt |
cmd2 |
( [ -z "$DEFINED" ] && cat || cmd3 ) |
cmd4 |
cmd5 |
cmd6 |
(...) |
cmdN > result.txt
답변2
if
// else
효율적인 fi
. Bourne과 유사한 쉘을 가정하면 다음과 같습니다.
cmd1 < input.txt |
cmd2 |
if [ -n "$DEFINED" ]; then cmd3; else cat; fi |
cmd4 |
cmd5 |
cmd6 |
(...) |
cmdN > result.txt
답변3
지금까지 제공된 모든 답변은 cmd3
다음 cat
명령 실행을 피할 수도 있습니다.
if [ -n "$DEFINE" ]; then
alias maybe_cmd3='cmd3 |'
else
alias maybe_cmd3=''
fi
cmd1 |
cmd2 |
maybe_cmd3
cmd4 |
... |
cmdN > result.txt
이는 POSIX이지만 - 모드 가 아닌 bash
스크립트 (예: - 로 시작하는 스크립트 )에 있는 경우 ( 또는 ) 를 사용하여 별칭 확장을 활성화 해야 합니다 .bash
sh
#! /path/to/bash -
shopt -s expand_aliases
set -o posix
불필요한 명령을 실행하지 않는 또 다른 방법은 eval을 사용하는 것입니다.
if [ -n "$DEFINE" ]; then
maybe_cmd3='cmd3 |'
else
maybe_cmd3=''
fi
eval "
cmd1 |
cmd2 |
$maybe_cmd3
cmd4 |
... |
cmdN > result.txt"
또는:
eval "
cmd1 |
cmd2 |
${DEFINE:+cmd3 |}
cmd4 |
... |
cmdN > result.txt"
Linux에서는 (적어도) + 대신 which를 cat
사용하여 두 파이프 간에 데이터를 전달할 수 있으므로 데이터가 커널과 사용자 공간 간에 두 번 이동하는 것을 방지할 수 있습니다.pv -q
splice()
read()
write()
cmd3
또 다른 옵션은 주어진 명령을 파이프로 연결하거나 파이프로 실행 하거나 이에 의존하지 않는 함수를 정의하는 것입니다 $DEFINE
.
if [ -n "$DEFINE" ]; then
maybe_preprocess_with_cmd3() { cmd3 | "$@"; }
maybe_postprocess_with_cmd3() { "$@" | cmd3; }
else
maybe_preprocess_with_cmd3() { "$@"; }
maybe_postprocess_with_cmd3() { "$@"; }
fi
그런 다음:
cmd1 |
cmd2 |
maybe_preprocess_with_cmd3 cmd4 |
... |
cmdN > result.txt
또는:
cmd1 |
maybe_postprocess_with_cmd3 cmd2 |
cmd4 |
... |
cmdN > result.txt
답변4
비슷한 상황이 발생하여 bash를 사용하여 해결했습니다.기능:
if ...; then
my_cmd3() { cmd3; }
else
my_cmd3() { cat; }
if
cmd1 < input.txt |
cmd2 |
my_cmd3 |
cmd4 |
cmd5 |
cmd6 |
(...) |
cmdN > result.txt