Bash에서는 다음이 있다고 가정합니다 var=a.b.c.
.
$ IFS=. printf "%s\n" $var
a.b.c
그러나 이러한 사용법은 IFS
배열을 생성할 때 적용됩니다.
$ IFS=. arr=($var)
$ printf "%s\n" "${arr[@]}"
a
b
c
물론 굉장히 편리한데, 이건 어디에 기록되는 걸까요? 다음 장을 빠르게 읽으세요.정렬또는분사Bash 문서에는 지침이 제공되지 않습니다. IFS
꿰뚫어 보고단일 페이지 문서이 효과에 대한 힌트도 제공되지 않습니다.
이 작업이 언제 안정적으로 수행될 수 있는지 잘 모르겠습니다.
IFS=x do something
그리고 이는 IFS
필드 분할에 영향을 미칠 것으로 예상됩니다.
답변1
기본 아이디어는 외부 명령이 실행될 때 실행 되도록 VAR=VALUE some-command
설정하는 것이며 그보다 더 멋진 것은 아닙니다. 이러한 직관을 쉘 작동 방식에 대한 지식과 결합하면 대부분의 경우 올바른 답을 얻을 수 있습니다. POSIX 참조는 다음과 같습니다.VAR
VALUE
some-command
some-command
"쉘 명령 언어" 장의 "간단한 명령".
만약 some-command
그것이라면외부 명령, VAR=VALUE some-command
와 동일합니다 env VAR=VALUE some-command
. VAR
은(는) 환경으로 내보내지며 some-command
셸의 값(또는 값 부족)은 변경되지 않습니다.
만약 some-command
그것이라면기능, 그러면 VAR=VALUE some-command
와 동일합니다 VAR=VALUE; some-command
. 즉,할당량이 여전히 존재함함수가 반환된 후에는 변수가 환경으로 내보내지지 않습니다. 그 이유는 Bourne 쉘의 설계(및 후속 하위 호환성)와 관련이 있습니다. 함수 실행 중에 변수 값을 저장하고 복원하는 기능이 없습니다. 함수는 셸 자체에서 실행되므로 변수를 내보내지 않는 것이 좋습니다. 그러나 ksh(ATT ksh93 및 pdksh/mksh 포함), bash 및 zsh는 VAR
함수 실행 중에만 설정되는 더 유용한 동작을 구현합니다(내보내기도 함). 존재하다케시function NAME …
, 표준 구문을 사용하여 정의된 함수가 아닌 ksh 구문을 사용하여 함수가 정의된 경우 이 작업을 수행합니다 NAME ()
. 존재하다세게 때리다, 이는 POSIX 모드(runtime 사용 시)가 아닌 bash 모드에서만 수행됩니다 POSIXLY_CORRECT=1
. 존재하다다루기 힘든posix_builtins
, 이 옵션이 설정되지 않은 경우 이 옵션이 기본적으로 설정되어 있지 않지만 emulate sh
또는 를 통해 설정할 수 있습니다 emulate ksh
.
내장 함수의 경우 some-command
동작은 내장 함수의 유형에 따라 달라집니다.특수 내장 기능함수처럼 동작합니다. 특수 내장 기능은 쉘 상태에 영향을 미치기 때문에(예: break
제어 흐름에 영향, cd
현재 디렉토리에 영향, set
위치 매개변수 및 옵션에 영향을 주기 때문에) 쉘 내부에서 구현되어야 합니다.기타 내장 기능내장 기능은 단지 성능과 편의를 위한 것이며(대부분 - 예를 들어 bash 기능은 printf -v
내장 기능으로만 구현할 수 있음) 외부 명령처럼 작동합니다.
별칭 확장 후에 할당이 발생하므로 if some-command
는 다음과 같습니다.별명, 먼저 확장하여 무슨 일이 일어나는지 확인하세요.
모든 경우에 할당은 명령줄 자체의 변수 대체를 포함하여 명령줄을 구문 분석한 후에 수행됩니다. 그래서 과제 전에 평가가 이루어지기 때문에 var=a; var=b echo $var
인쇄됩니다 . 따라서 이전 값을 사용하여 분할합니다 .a
$var
IFS=. printf "%s\n" $var
IFS
$var
모든 유형의 명령을 다루었지만 상황이 한 가지 더 있습니다.실행할 명령이 없습니다., 즉 명령에 할당(및 리디렉션도 가능)만 포함된 경우입니다. 이 경우,할당량이 여전히 존재함. VAR=VALUE OTHERVAR=OTHERVALUE
와 동일합니다 VAR=VALUE; OTHERVAR=OTHERVALUE
. 따라서 그 후에도 IFS=. arr=($var)
여전히 IFS
로 설정되어 있습니다 .
. $IFS
과제에서 ~를 사용할 수 arr
있고 해당 과제가 이미 새로운 값을 가질 것으로 예상할 수 있으므로 IFS
확장을 위해 의 새 값을 사용하는 것이 합리적입니다 $var
.
간단히 말해서, 당신은 IFS
사용할 수 있습니다일시적인필드 분할만 해당:
- 새 셸 또는 하위 셸을 시작합니다(예를 들어 값에 2자 미만의 문자가 포함된 경우 다르게 동작한다는 점을 제외하면 이는
third=$(IFS=.; set -f; set -- $var; echo "$3")
복잡한 접근 방식입니다 ).third=${var#*.*.}
var
.
- ksh에서 with는 ksh 구문을 사용하여 정의
IFS=. some-function
됩니다 .some-function
function some-function …
IFS=. some-function
Bash 및 zsh에서는 호환 모드가 아닌 기본 모드에서 실행되는 한 .
답변2
@Gilles의 답변은 정말 훌륭합니다. 그는 복잡한 문제를 자세히 설명합니다.
그러나 나는 이 명령이 왜 필요한지에 대한 답을 믿습니다.
$ IFS=. printf "%s\n" $var
a.b.c
작동 방식은 간단합니다. 전체 명령줄은 다음과 같습니다.이전에 구문 분석됨실행되었습니다. 각 "단어"는 쉘에 의해 한 번 처리됩니다.
이것예를 들어 작업이 IFS=.
지연됩니다.(네 번째 단계가 마지막 단계입니다):
4.- 각 변수 할당을 확장해야 합니다...
명령을 실행하기 전에 인수의 모든 확장이 먼저 처리되어 다음 실행 가능 라인을 빌드합니다.
$ IFS=. printf "%s\n" a.b.c ## IFS=. goes to the environment.
a.b.c
명령에 인수 및 가 제공되기 전에 값은 $var
"이전" IFS로 확장됩니다.a.b.c
printf
"%s\n"
a.b.c
평가하다
첫 번째 수준 대기 시간은 다음과 같은 방법으로 도입될 수 있습니다 eval
.
$ IFS=. eval printf "'%s\n'" \$var
a
b
c
해당 행은 "IFS="를 사용하여 (처음으로) 구문 분석됩니다. 환경은 다음과 같이 설정됩니다.
$ printf '%s\n' $var
그런 다음 다시 다음과 같이 해결됩니다.
$ printf '%s\n' a b c
그리고 이것을 실행하세요:
a
b
c
(abc) 값은 $var
사용 중인 IFS 값과 구분됩니다 .
.
환경
복잡하고 까다로운 부분은 언제, 어떤 맥락에서 작동하는지입니다!
Giles의 답변의 첫 번째 부분은 이것을 매우 잘 설명합니다.
한 가지 추가 세부 사항이 있습니다.
이 명령을 실행할 때:
$ IFS=. arr=($var)
IFS의 가치는 현재 환경에서 유지됩니다. 예:
$ printf '<%s> ' "${arr[@]}" "$IFS"
<a> <b> <c> <.>
IFS는 개별 명세서에 사용됩니다.
하지만 다음과 같은 경우는 피할 수 있습니다.단일 문에 대해 IFS 설정
$ IFS=. command eval arr\=\(\$var\)
$ printf '<%s> ' "${arr[@]}" "$IFS"
<a> <b> <c> <
>
답변3
귀하의 질문에 대해
var=a.b.c
IFS=. printf "%s\n" $var
그것은 극단적인 상황이다.
이는 macro expansion
명령에서 발생하는 일 때문입니다.앞으로쉘 변수가 IFS=.
설정되었습니다.
즉, $var
확장되면 이전 IFS
값이 활성화된 다음 IFS
으로 설정됩니다 '.'
.