뭔가 완전히 잘못된 것이 있을 수 있지만 IFS를 다음 중 하나로 설정하면 설득력이 있는 것 같습니다.주문하다사전 완료/완료 목록에는 전혀 영향을 미치지 않습니다.
외부 IFS( while
구성 외부)는 아래 스크립트에 표시된 모든 예에서 지배적입니다.
여기서 무슨 일이 일어나고 있는 걸까요? 이 경우 IFS가 수행하는 작업에 대해 내가 잘못된 생각을 갖고 있습니까? 배열 분할 결과가 "예상" 열에 표시된 대로일 것으로 예상했습니다.
#!/bin/bash
xifs() { echo -n "$(echo -n "$IFS" | xxd -p)"; } # allow for null $IFS
show() { x=($1)
echo -ne " (${#x[@]})\t |"
for ((j=0;j<${#x[@]};j++)); do
echo -n "${x[j]}|"
done
echo -ne "\t"
xifs "$IFS"; echo
}
data="a b c"
echo -e "----- -- -- \t --------\tactual"
echo -e "outside \t IFS \tinside"
echo -e "loop \t Field \tloop"
echo -e "IFS NR NF \t Split \tIFS (actual)"
echo -e "----- -- -- \t --------\t-----"
IFS=$' \t\n'; xifs "$IFS"; echo "$data" | while read; do echo -ne '\t 1'; show "$REPLY"; done
IFS=$' \t\n'; xifs "$IFS"; echo "$data" | while IFS= read; do echo -ne '\t 2'; show "$REPLY"; done
IFS=$' \t\n'; xifs "$IFS"; echo "$data" | while IFS=b read; do echo -ne '\t 3'; show "$REPLY"; done
IFS=" "; xifs "$IFS"; echo "$data" | while read; do echo -ne '\t 4'; show "$REPLY"; done
IFS=" "; xifs "$IFS"; echo "$data" | while IFS= read; do echo -ne '\t 5'; show "$REPLY"; done
IFS=" "; xifs "$IFS"; echo "$data" | while IFS=b read; do echo -ne '\t 6'; show "$REPLY"; done
IFS=; xifs "$IFS"; echo "$data" | while read; do echo -ne '\t 7'; show "$REPLY"; done
IFS=; xifs "$IFS"; echo "$data" | while IFS=" " read; do echo -ne '\t 8'; show "$REPLY"; done
IFS=; xifs "$IFS"; echo "$data" | while IFS=b read; do echo -ne '\t 9'; show "$REPLY"; done
IFS=b; xifs "$IFS"; echo "$data" | while IFS= read; do echo -ne '\t10'; show "$REPLY"; done
IFS=b; xifs "$IFS"; echo "$data" | while IFS=" " read; do echo -ne '\t11'; show "$REPLY"; done
echo -e "----- -- -- \t --------\t-----"
산출:
----- -- -- -------- actual
outside IFS inside assigned
loop Field loop # inner
IFS NR NF Split IFS # expected IFS
----- -- -- -------- ----- # --------- --------
20090a 1 (3) |a|b|c| 20090a #
20090a 2 (3) |a|b|c| 20090a # |a b c| IFS=
20090a 3 (3) |a|b|c| 20090a # |a | c| IFS=b
20 4 (3) |a|b|c| 20 #
20 5 (3) |a|b|c| 20 # |a b c IFS=
20 6 (3) |a|b|c| 20 # |a | c| IFS=b
7 (1) |a b c| #
8 (1) |a b c| # |a|b|c| IFS=" "
9 (1) |a b c| # |a | c| IFS=b
62 10 (2) |a | c| 62 # |a b c| IFS=
62 11 (2) |a | c| 62 # |a|b|c| IFS=" "
----- -- -- -------- ----- --------- -------
답변1
(설명이 길어서 죄송합니다)
예, IFS
in 의 변수는 while IFS=" " read; do …
나머지 코드에 영향을 주지 않습니다.
먼저 쉘 명령줄에 두 가지 다른 유형의 변수가 있음을 지정합니다.
- 셸 변수(셸 내에서만 존재하며 셸의 지역 변수임)
- 모든 프로세스에는 환경 변수가 존재합니다. 이는 일반적으로 저장되므로
fork()
하위exec()
프로세스가 이를 상속합니다.
다음을 사용하여 명령을 호출하는 경우:
A=foo B=bar command
A
foo
명령은 (환경) 변수가 로 B
설정된 환경에서 실행됩니다 bar
. 하지만 이 명령줄을 사용하면 현재 쉘 변수 A
와B
끊임없는.
이는 다음과 다릅니다.
A=foo; B=bar; command
A
쉘 변수 및 는 여기에 정의되어 B
있으며 명령은 환경 변수 A
및 B
정의 없이 실행됩니다. A
및 의 값은 B
에서 액세스할 수 없습니다 command
.
그러나 일부 쉘 변수가 -ed되면 export
해당 환경 변수는 해당 쉘 변수와 동기화됩니다. 예:
export A
export B
A=foo; B=bar; command
이 코드를 사용하면 둘 다껍데기변수와 쉘환경변수는 foo
및 로 설정됩니다 bar
. 환경 변수는 하위 프로세스에 상속되므로 command
해당 값에 액세스할 수 있습니다.
원래 질문으로 돌아가려면 다음으로 이동하세요.
IFS='a' read
영향을 받을 뿐입니다 read
. 사실 이 경우 read
변수의 값은 중요하지 않습니다 IFS
. IFS
행을 분할하고 여러 변수에 저장해야 하는 경우에만 사용하세요. 예를 들면 다음과 같습니다.
echo "a : b : c" | IFS=":" read i j k; \
printf "i is '%s', j is '%s', k is '%s'" "$i" "$j" "$k"
IFS
read
매개변수를 사용하여 호출하지 않으면 사용되지 않습니다. (편집하다:이는 완전히 정확하지는 않습니다. IFS
입력 줄의 시작/끝에 있는 공백 문자(예: 공백 및 탭)는 항상 무시됩니다. )
답변2
간단히 말해서,한 번에 여러 변수를 읽어야 합니다.example1IFS=<something> read ...
에서 구성이 눈에 띄는 효과를 갖도록 하세요 .
read
귀하의 예에서 범위를 놓쳤습니다. 가지다아니요테스트 케이스 루프 내에서 IFS를 수정합니다. 각 라인에서 두 번째 IFS가 수행하는 작업을 정확히 지적하겠습니다.
IFS=$' \t\n'; xifs "$IFS"; echo "$data" | while IFS=b read; do echo ...
^ ^
| |
from here --' `- to here :)
이는 쉘에서 실행되는 모든 프로그램과 같습니다. 명령줄에서 (재)정의하는 변수는 프로그램 실행에 영향을 줍니다. 그리고오직(수출하지 않기 때문에). 따라서 그러한 행에서 재정의를 사용하려면 값을 할당하도록 IFS
요청해야 합니다 .read
여러 변수. 다음 예를 확인하세요.
$ data="a b c"
$ echo "$data" | while read A B C; do echo \|$A\|$B\|\|$C\|; done
|a|b||c|
$ echo "$data" | while IFS= read A B C; do echo \|$A\|$B\|\|$C\|; done
|a b c||||
$ echo "$data" | while IFS='a' read A B C; do echo \|$A\|$B\|\|$C\|; done
|| b c|||
$ echo "$data" | while IFS='ab' read A B C; do echo \|$A\|$B\|\|$C\|; done
|| || c|
1 방금 배운대로자일스에서, 하나의 필드만 읽을 때 (공백)로 설정하면 실제로 이점이 있을 수 있습니다 IFS=''
. 즉, 줄 시작 부분에서 공백이 잘리는 것을 방지합니다.