Q1. 필드 분할.
필드 분할은 단어 분할과 동일합니까?
예, 둘 다 같은 생각을 가리 킵니다.
Q2 : IFS 는 언제 null 입니까?
IFS=''
빈 문자열과 동일한 null로 설정 합니까?
예, 세 가지 모두 동일합니다. 필드 / 단어 분할을 수행하지 않아야합니다. 또한 이것은 (와 마찬가지로 echo "$*"
) 인쇄 필드에 영향을 미치며 모든 필드는 공간없이 함께 연결됩니다.
Q3 : (파트 a) Unset IFS.
POSIX 사양 에서 다음을 읽었습니다 .
IFS가 설정되어 있지 않으면 쉘은 IFS 값이 <space> <tab> <newline> 인 것처럼 동작합니다 .
다음과 정확히 동일합니다.
를 사용하면 unset IFS
쉘은 IFS가 기본값 인 것처럼 동작합니다.
이는 '필드 분할'이 기본 IFS 값과 정확히 동일하거나 설정되지 않음을 의미합니다.
그렇다고 IFS가 모든 조건에서 동일한 방식으로 작동한다는 의미는 아닙니다. 보다 구체적으로 실행 OldIFS=$IFS
하면 var OldIFS
가 기본값이 아닌 null로 설정됩니다. 이와 같이 IFS를 다시 설정하려고하면 IFS=OldIFS
IFS가 null로 설정되어 이전과 같이 설정되지 않은 상태로 유지됩니다. 조심해 !!.
Q3 : (파트 b) IFS 복원.
IFS 값을 기본값으로 복원하는 방법 IFS의 기본값을 복원하고 싶다고 가정 해보십시오. 어떻게합니까? (더 구체적으로, <tab> 및 <newline>을 어떻게 참조합니까?)
zsh, ksh 및 bash (AFAIK)의 경우 IFS를 다음과 같이 기본값으로 설정할 수 있습니다.
IFS=$' \t\n' # works with zsh, ksh, bash.
완료, 당신은 다른 것을 읽을 필요가 없습니다.
그러나 sh에 대해 IFS를 다시 설정해야하는 경우 복잡해질 수 있습니다.
단점을 제외하고 가장 쉬운 방법부터 완료 해 봅시다 (복잡성 제외).
IFS를 설정 해제합니다.
우리는 단지 unset IFS
(위의 Q3 부분 a를 읽으십시오).
스왑 문자.
이 문제를 해결하려면 tab과 newline의 값을 바꾸면 IFS의 값을 더 간단하게 설정 한 다음 동일한 방식으로 작동합니다.
IFS를 <space> <newline> <tab>으로 설정하십시오 .
sh -c 'IFS=$(echo " \n\t"); printf "%s" "$IFS"|xxd' # Works.
3. 간단한? 해결책:
IFS를 올바르게 설정해야하는 하위 스크립트가있는 경우 언제든지 수동으로 작성할 수 있습니다.
IFS = '
'
어디 수동으로 입력 순서가 있었다 : IFS=
'spacetabnewline'실제로 제대로 (당신이 확인해야하는 경우,이 대답을 편집) 위의 입력 된 순서. 그러나 브라우저가 공백을 쥐어 짜거나 숨기기 때문에 브라우저에서 복사 / 붙여 넣기가 중단됩니다. 위에서 설명한대로 코드를 공유하기가 어렵습니다.
완벽한 솔루션.
안전하게 복사 할 수있는 코드를 작성하려면 일반적으로 명확한 인쇄 가능한 이스케이프가 필요합니다.
예상 값을 "생성하는"코드가 필요합니다. 그러나 개념적으로 정확 하더라도이 코드는 후행을 설정하지 않습니다 \n
.
sh -c 'IFS=$(echo " \t\n"); printf "%s" "$IFS"|xxd' # wrong.
대부분의 셸 에서 확장 후 모든 줄 바꿈 $(...)
또는 `...`
명령 대체가 제거 되기 때문에 발생합니다 .
우리는 sh에 대한 트릭 을 사용해야합니다 .
sh -c 'IFS="$(printf " \t\nx")"; IFS="${IFS%x}"; printf "$IFS"|xxd' # Correct.
다른 방법은 bash에서 환경 값으로 IFS를 설정 한 다음 (예 : 환경을 통해 IFS가 설정되도록 허용하는 버전) sh를 호출하는 것입니다.
env IFS=$' \t\n' sh -c 'printf "%s" "$IFS"|xxd'
간단히 말해 sh는 IFS를 기본값으로 재설정하는 것이 매우 이상한 모험입니다.
Q4 : 실제 코드에서 :
마지막으로,이 코드는 어떻게 :
while IFS= read -r line
do
echo $line
done < /path_to_text_file
첫 줄을 다음과 같이 바꾸면
while read -r line # Use the default IFS value
또는
while IFS=' ' read -r line
첫째 : echo $line
(var NOT 인용 된)이 Porpouse에 있는지 여부는 알 수 없습니다. 읽기에는없는 두 번째 레벨의 '필드 분할'을 소개합니다. 둘 다 대답하겠습니다. :)
이 코드를 사용하면 확인할 수 있습니다. 유용한 xxd 가 필요합니다 :
#!/bin/ksh
# Correctly set IFS as described above.
defIFS="$(printf " \t\nx")"; defIFS="${defIFS%x}";
IFS="$defIFS"
printf "IFS value: "
printf "%s" "$IFS"| xxd -p
a=' bar baz quz '; l="${#a}"
printf "var value : %${l}s-" "$a" ; printf "%s\n" "$a" | xxd -p
printf "%s\n" "$a" | while IFS='x' read -r line; do
printf "IFS --x-- : %${l}s-" "$line" ;
printf "%s" "$line" |xxd -p; done;
printf 'Values quoted :\n' "" # With values quoted:
printf "%s\n" "$a" | while IFS='' read -r line; do
printf "IFS null quoted : %${l}s-" "$line" ;
printf "%s" "$line" |xxd -p; done;
printf "%s\n" "$a" | while IFS="$defIFS" read -r line; do
printf "IFS default quoted : %${l}s-" "$line" ;
printf "%s" "$line" |xxd -p; done;
unset IFS; printf "%s\n" "$a" | while read -r line; do
printf "IFS unset quoted : %${l}s-" "$line" ;
printf "%s" "$line" |xxd -p; done;
IFS="$defIFS" # set IFS back to default.
printf "%s\n" "$a" | while IFS=' ' read -r line; do
printf "IFS space quoted : %${l}s-" "$line" ;
printf "%s" "$line" |xxd -p; done;
printf '%s\n' "Values unquoted :" # Now with values unquoted:
printf "%s\n" "$a" | while IFS='x' read -r line; do
printf "IFS --x-- unquoted : "
printf "%s, " $line; printf "%s," $line |xxd -p; done
printf "%s\n" "$a" | while IFS='' read -r line; do
printf "IFS null unquoted : ";
printf "%s, " $line; printf "%s," $line |xxd -p; done
printf "%s\n" "$a" | while IFS="$defIFS" read -r line; do
printf "IFS defau unquoted : ";
printf "%s, " $line; printf "%s," $line |xxd -p; done
unset IFS; printf "%s\n" "$a" | while read -r line; do
printf "IFS unset unquoted : ";
printf "%s, " $line; printf "%s," $line |xxd -p; done
IFS="$defIFS" # set IFS back to default.
printf "%s\n" "$a" | while IFS=' ' read -r line; do
printf "IFS space unquoted : ";
printf "%s, " $line; printf "%s," $line |xxd -p; done
나는 얻다:
$ ./stackexchange-Understanding-IFS.sh
IFS value: 20090a
var value : bar baz quz -20202062617220202062617a20202071757a2020200a
IFS --x-- : bar baz quz -20202062617220202062617a20202071757a202020
Values quoted :
IFS null quoted : bar baz quz -20202062617220202062617a20202071757a202020
IFS default quoted : bar baz quz-62617220202062617a20202071757a
IFS unset quoted : bar baz quz-62617220202062617a20202071757a
IFS space quoted : bar baz quz-62617220202062617a20202071757a
Values unquoted :
IFS --x-- unquoted : bar, baz, quz, 6261722c62617a2c71757a2c
IFS null unquoted : bar, baz, quz, 6261722c62617a2c71757a2c
IFS defau unquoted : bar, baz, quz, 6261722c62617a2c71757a2c
IFS unset unquoted : bar, baz, quz, 6261722c62617a2c71757a2c
IFS space unquoted : bar, baz, quz, 6261722c62617a2c71757a2c
첫 번째 값은 올바른 값입니다 IFS=
'spacetabnewline'
다음 줄은 var $a
가 가진 모든 16 진 값이며, 각 읽기 명령에 주어질 때 줄 바꿈 '0a'입니다.
IFS가 null 인 다음 행은 '필드 분할'을 수행하지 않지만 줄 바꿈이 제거됩니다 (예상대로).
다음 세 줄은 IFS에 공백이 포함되어 있으므로 초기 공백을 제거하고 var 행을 나머지 잔액으로 설정하십시오.
마지막 네 줄은 따옴표없는 변수의 기능을 보여줍니다. 값이 (여러) 공백으로 분할되고 다음과 같이 인쇄됩니다.bar,baz,qux,
IFS
것과 설정되지 않은IFS
것은 매우 다릅니다. Q4에 대한 대답은 부분적으로 잘못되었습니다. 내부 구분 기호는 여기에 닿지 않고 앞뒤 구분자 만 만집니다.