나는 보통 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
context
5번째와 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