/bin/sh
BSD 플랫폼의 POSIX 쉘()에서 여러 줄 문자열을 처리하고 한 줄씩 반복하고 싶습니다. Bash는 기본 BSD 배포판에 포함되어 있지 않으며 GPL에 따라 라이센스가 부여되어 있으므로 일반적으로 사용할 수 있도록 노력하고 있습니다 /bin/sh
.
파이프를 사용하여 솔루션을 찾았지만 일반 /bin/sh
셸에서는 이러한 솔루션이 별도의 프로세스로 처리되므로 다음이 작동하지 않습니다.
MULTILINE="`cat ${SOMEFILE}`"
SOMEVAR="original value"
echo "${MULTILINE}" | while IFS= read -r SINGLELINE
do
SOMEVAR="updated value"
echo "this is a single line: ${SINGLELINE}"
echo "SOMEVAR is now: ${SOMEVAR}"
done
echo "Final SOMEVAR is unchanged: ${SOMEVAR}"
${SOMEVAR}
위의 예에서는 변수 변경(즉, while 루프 외부에서 액세스할 수 없음)을 제외하고 내가 원하는 작업을 수행합니다.
내 질문: 이 제한 없이 비슷한 작업을 어떻게 수행할 수 있습니까? 많은 솔루션에는 Bash가 필요하지만 저는 표준 POSIX-shell을 사용하고 있습니다 /bin/sh
.
답변1
여기에서 설명서를 사용할 수 있습니다.
while IFS= read -r SINGLELINE
do
SOMEVAR="updated value"
printf '%s\n' "this is a single line: ${SINGLELINE}"
printf '%s\n' "SOMEVAR is now: ${SOMEVAR}"
done << EOF
$MULTILINE
EOF
printf '%s\n' "Final SOMEVAL is still $SOMEVAR"
sh
구현 에 따라 여기 문서는 삭제된 임시 파일(쉘이 변수의 확장과 개행 문자를 미리 저장함) 또는 쉘이 변수의 확장과 그 뒤에 오는 파이프를 제공하는 파이프로 구현됩니다. 개행. 두 경우 모두 리디렉션된 명령은 원래 Bourne 셸(현재는 더 이상 사용되지 않으며 POSIX 호환 셸이 아님) 이외의 하위 셸(POSIX에서 요구하는 대로)에서 실행되지 않습니다.
또는 분할+glob을 사용할 수 있습니다.
IFS='
' # split on newline only
set -o noglob
for SINGLELINE in $MULTILINE
do
SOMEVAR="updated value"
printf '%s\n' "this is a single line: ${SINGLELINE}"
printf '%s\n' "SOMEVAR is now: ${SOMEVAR}"
done
printf '%s\n' "Final SOMEVAL is still $SOMEVAR"
그러나 빈 줄은 건너뜁니다.
답변2
파이프 없이 파일에서 직접 읽을 수 있습니다. 이렇게 하면 서브셸에서 루프가 실행되는 것을 방지하므로 while
루프 후에 변경된 값을 볼 수 있습니다 .$SOMEVALUE
SOMEVAR="original value"
while IFS= read -r SINGLELINE
do
SOMEVAR="updated value"
printf 'this is a single line: %s\n' "$SINGLELINE"
printf 'SOMEVAR is now: %s\n' "$SOMEVAR"
done <"$SOMEFILE"
printf 'Final SOMEVAR is: %s\n' "$SOMEVAR"
변수 사용을 고집한다면 $MULTILINE
파일에 쓰고 거기에서 읽으십시오.
tmpfile=$(mktemp)
printf '%s\n' "$MULTILINE" >"$tmpfile"
while ...; do
...
done <"$tmpfile"
rm "$tmpfile"
또한 관련:
$SOMEVAR
위에 링크된 질문에 대한 답변에서는 모든 사용이 파이프 끝의 하위 쉘에서 발생하는 방식으로 프로그램을 작성하는 것이 좋습니다 .
MULTILINE=$(cat "$SOMEFILE")
SOMEVAR="original value"
printf '%s\n' "$MULTILINE" | {
while IFS= read -r SINGLELINE
do
SOMEVAR="updated value"
printf 'this is a single line: %s\n' "$SINGLELINE"
printf 'SOMEVAR is now: %s\n' "$SOMEVAR"
done
printf 'Final SOMEVAR is: %s\n' "$SOMEVAR"
}
또한 관련될 수 있습니다:
관심을 가질 수 있는 기타 질문:
답변3
이것은 나에게 효과적입니다.
$ cat bin/test
#! /bin/sh
SOMEFILE=$1
MULTILINE="`cat ${SOMEFILE}`"
SOMEVAR="blah"
echo "${MULTILINE}" | while IFS= read -r SINGLELINE
do
echo "this is a single line: ${SINGLELINE}"
echo "but accessing this var fails: ${SOMEVAR}"
done
그리고
$ bin/test bin/test
this is a single line: #! /bin/sh
but accessing this var fails: blah
this is a single line: SOMEFILE=$1
but accessing this var fails: blah
this is a single line: MULTILINE="`cat ${SOMEFILE}`"
but accessing this var fails: blah
this is a single line: SOMEVAR="blah"
but accessing this var fails: blah
this is a single line:
but accessing this var fails: blah
this is a single line: echo "${MULTILINE}" | while IFS= read -r SINGLELINE
but accessing this var fails: blah
this is a single line: do
but accessing this var fails: blah
this is a single line: echo "this is a single line: ${SINGLELINE}"
but accessing this var fails: blah
this is a single line: echo "but accessing this var fails: ${SOMEVAR}"
but accessing this var fails: blah
this is a single line: done
but accessing this var fails: blah