내 함수가 파이프의 입력으로 호출되었는지 어떻게 확인하나요?

내 함수가 파이프의 입력으로 호출되었는지 어떻게 확인하나요?

나는 보통 if [ -t 0 ]stdin을 테스트하고 if [ -t 1 ]stdin과 stdout이 TTY인지 확인하고, 그렇지 않다면 파이프라고 가정합니다. 나는 최근에 이것이 잘못된 가정이라는 것을 깨달았습니다.

function context()
{
    if [ -t 0 ]
    then
        if [ -t 1 ]
        then
            echo "no pipes"
        else
            echo "pipe out only"
        fi
    else
        if [ -t 1 ]
        then
            echo "pipe in only"
        else
            echo "pipe in and out"
        fi
    fi
}

echo "No Loop:"        # these cases work as desired
context
echo 'f' | context
echo 'f' | context | cat
context | cat

echo
echo "Loop:"
echo $'foo
bar' | while read x
do
    context             # I want this to say "no pipes"
    echo 'f' | context
done

위 bash의 출력은 다음과 같습니다:

No Loop:
no pipes
pipe in only
pipe in and out
pipe out only

Loop:
pipe in only
pipe in only
pipe in only
pipe in only

context5번째와 7번째 호출이 "파이프 없음"을 인쇄하도록 to의 정의를 어떻게 변경합니까 ?

즉, stdin이 터미널이 아닌지 테스트하는 대신(문제를 일으킬 수 있음) 이 특정 함수의 stdin이 파이프인지 테스트하고 싶습니다. -p명명된 파이프인지 확인하는 것을 보았지만 익명 파이프에 사용하고 싶습니다.

편집하다

실제 사용 사례에는 theDb대신 호출할 함수가 포함됩니다 context. 이상적으로 다음 두 사례는 상황에 관계없이 동일합니다.

cat file_with_some_sql | theDb
theDb "sql goes here"

답변1

이유"파이프 입력 전용"네 번 발생하는 것은 실제로 context함수가 제대로 작동하기 때문입니다.echo $'foo bar' | while read x 등.파이프입니다 -모든 것루프가 while파이프에서 입력을 받습니다. 원하는 출력을 얻으려면 while루프를 for루프로 변경하고 아무 것도 파이프로 연결하지 마십시오 for.

for x in foo bar; do  context ;  echo 'f' | context; done

산출:

no pipes
pipe in only
no pipes
pipe in only

OP 코드가 어디에서 잘못되었는지 확인하려면 for루프에 몇 가지 내용을 입력하고 무슨 일이 일어나는지 확인하세요.

echo | for x in foo bar; do  context ;  echo 'f' | context; done

산출:

pipe in only
pipe in only
pipe in only
pipe in only

초보자는 while read x모든 표준 입력이 소비된다고 (잘못) 생각할 수도 있지만, 사실은 그렇지 않습니다. read내부 루프 가 포함된 다음 예제를 고려해보세요 while.

printf '%s\n' foo bar baz buzz | 
while read x; do echo $x; read y; echo ${y^^} ;done

산출:

foo
BAR
baz
BUZZ

관련 정보