while 루프 내에서 bash에서 입력 읽기


97

다음과 같은 bash 스크립트가 있습니다.

cat filename | while read line
do
    read input;
    echo $input;
done

그러나 이것은 내가 while 루프에서 읽을 때 가능한 I / O 리디렉션으로 인해 파일 파일 이름에서 읽으려고 할 때 올바른 출력을 제공하지 않습니다.

같은 일을하는 다른 방법이 있습니까?


당신이 스크립트에서 전환 사용자로 읽기 명령을 bash는 사용자를 전환 실행하면 같은 일이 발생
krupal

답변:



55

일반 stdin을 유닛 3을 통해 리디렉션하여 파이프 라인 내부를 유지할 수 있습니다.

{ cat notify-finished | while read line; do
    read -u 3 input
    echo "$input"
done; } 3<&0

BTW, 정말로 cat이런 식으로 사용 하고 있다면 리디렉션으로 바꾸면 일이 훨씬 쉬워집니다.

while read line; do
    read -u 3 input
    echo "$input"
done 3<&0 <notify-finished

또는 해당 버전에서 stdin과 unit 3을 바꿀 수 있습니다. unit 3으로 파일을 읽고 stdin은 그대로 두십시오.

while read line <&3; do
    # read & use stdin normally inside the loop
    read input
    echo "$input"
done 3<notify-finished

두 번째 스크립트가 중단 된 이유는 무엇입니까?
Luca Borrione 2013

2
@LucaBorrione : 어떻게 사용하고 있습니까? 그것은 당신이 입력을 줄 때까지 기다리고 있습니까 ( read linenotify-finished에서 읽고 있지만 쓰여진대로 실행 read -u 3 input하면 콘솔에서 읽는 것 입니다)?
Gordon Davisson 2013

4

다음과 같이 루프를 변경하십시오.

for line in $(cat filename); do
    read input
    echo $input;
done

단위 테스트 :

for line in $(cat /etc/passwd); do
    read input
    echo $input;
    echo "[$line]"
done

@ w2lame 다시 테스트 한 후 "while"루프를 "for"루프로 변경하십시오. 여기서 오류가보고 "섹스는 -x"시도하는 것은에서 온다
dimba

4
고양이를 사용하지 마십시오. Hai Vu의 답변 참조
Fredrik Pihl 2011

+1. 이것은 다른 제안보다 내 특정 요구에 대해 구현하기가 훨씬 쉬웠습니다.
Nathan Wallace

1
Wooledge wiki의 Do n't Read Lines With For 를 참조하십시오 . 또한 shellcheck.net 경고 SC2013
Charles Duffy

3

두 번 읽은 것처럼 보이지만 while 루프 내부에서 읽을 필요가 없습니다. 또한 cat 명령을 호출 할 필요가 없습니다.

while read input
do
    echo $input
done < filename

4
OP의 목표는 루프 내부의 읽기가 사용자로부터 오는 반면 외부는 파일에서 읽는 것입니다. 따라서 그들은 합법적으로 두 개의 다른 소스에서 두 개의 다른 읽기를 원합니다. 이것은 질문의 텍스트 (내부 read의 행동을 "파일에서 읽기를 시도하기 때문에 옳지 않다"로 설명하는 것)와 그 대답 모두에서 분명합니다 filename.
Charles Duffy

1

이 매개 변수 -u를 읽었습니다.

"-u 1"은 "표준 입력에서 읽기"를 의미합니다.

while read -r newline; do
    ((i++))
    read -u 1 -p "Doing $i""th file, called $newline. Write your answer and press Enter!"
    echo "Processing $newline with $REPLY" # united input from two different read commands.
done <<< $(ls)

-6
echo "Enter the Programs you want to run:"
> ${PROGRAM_LIST}
while read PROGRAM_ENTRY
do
   if [ ! -s ${PROGRAM_ENTRY} ]
   then
      echo ${PROGRAM_ENTRY} >> ${PROGRAM_LIST}
   else
      break
   fi
done
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.