":"으로 구분된 값 목록이 있는데 하나씩 처리하고 싶습니다.
구분 기호가 공백이면 문제가 없습니다.
nuclear@korhal:~$ for a in 720 500 560 130; do echo $a; done
720
500
560
130
그러나 IFS(Internal Field Separator)를 다음과 같이 설정한 후 이상한 일이 발생하기 시작했습니다.
nuclear@korhal:~$ IFS=":" for a in 720:500:560:130; do echo $a; done;
bash: syntax error near unexpected token `do'
IFS를 설정할 때 모든 세미콜론을 건너뛰는 경우:
nuclear@korhal:~$ IFS=":" for a in 720:500:560:130 do echo $a done;
Command 'for' not found, did you mean:
command 'vor' from deb vor (0.5.8-1)
command 'fop' from deb fop (1:2.5-1)
command 'tor' from deb tor (0.4.4.5-1)
command 'forw' from deb mailutils-mh (1:3.9-3.2)
command 'forw' from deb mmh (0.4-2)
command 'forw' from deb nmh (1.7.1-7)
command 'sor' from deb pccts (1.33MR33-6build1)
command 'form' from deb form (4.2.1+git20200217-1)
command 'fox' from deb objcryst-fox (1.9.6.0-2.2)
command 'fort' from deb fort-validator (1.4.0-1)
command 'oor' from deb openoverlayrouter (1.3.0+ds1-3)
Try: sudo apt install <deb name>
Bash는 for 명령을 전혀 인식하지 못합니다. 이 경우 IFS가 설정되지 않은 경우 더 많은 출력이 필요하기 때문에 프롬프트가 표시됩니다(정상 동작).
IFS를 사용자 정의 문자로 설정하면 어떻게 됩니까? for 루프가 작동하지 않는 이유는 무엇입니까?
저는 Kubuntu 20.10 Bash 버전 5.0.17을 사용하고 있습니다.
답변1
할당 후 키워드가 인식되지 않습니다. 따라서 ( 있는 경우) 라는 일반 명령을 실행합니다 for
.IFS=blah for ...
for
$ cat > ./for
#!/bin/sh
echo script for
$ chmod +x ./for
$ PATH=$PATH:.
$ for x in a b c
> ^C
$ foo=bar for x in a b c
script for
그러나 Bash는 실행하기 전에 전체 입력 줄을 구문 분석하므로 이 키워드는 do
그 전에 구문 오류를 발생시킵니다.
이는 할당 대신 리디렉션을 사용하는 것과 유사합니다. 복합 명령 앞에 리디렉션 입력을 지정할 수 있나요?그리고 또한 보았다while 루프의 입력 리디렉션 연산자 순서를 바꿀 수 없는 이유는 무엇입니까?문법이 정의되는 방법에 대한 세부정보입니다.
또한보십시오:bash for 루프에서 임시 환경 변수를 사용하는 방법은 무엇입니까?
내 Zsh는 더 엄격합니다.
$ zsh -c 'foo=bar for x in a b c'
zsh:1: parse error near `for'
그러나 Zsh는 복합 명령 이전에 리디렉션을 허용합니다. 그러면 다음 세 줄이 출력됩니다 test.txt
.
$ zsh -c '> test.txt for x in a b c ; do echo $x; done '
또한 IFS
정적 문자열을 분할하는 데는 사용되지 않습니다. 예를 들어 720:500:560:130
토큰화는 확장에서만 작동합니다. 그래서:
$ IFS=":"
$ for a in 720:500:560:130; do echo "$a"; done;
720:500:560:130
하지만,
$ IFS=":"
$ s=720:500:560:130
$ for a in $s; do echo "$a"; done;
720
500
560
130
답변2
~을 위한
~처럼POSIX 요구 사항특정 단어( 포함 for
)는 다음과 같아야 합니다.
- 명령의 첫 번째 단어
- Case, for, in을 제외한 예약어 중 하나 뒤의 첫 번째 단어
- 경우 명령의 세 번째 단어(이 경우에만 유효함)
- for 명령의 세 번째 단어(이 경우 in 및 do만 유효함)
여기서는 상황이 다릅니다. 이것이 for
쉘이 오류를 이해하고 보고할 수 없는 이유입니다.
임시 IFS에 관한 이 질문은 다음과 관련이 있습니다.필드 분할을 위해 언제 임시 IFS를 사용할 수 있습니까?. 그러나 그 대답은 단순한 명령에만 적용됩니다(복합 명령입니다).
또한:
IFS
IFS의 가치는 오직 영향을 미칩니다확장하다(변수 확장).
IFS 값을 적용하려면 이전 명령에서 설정해야 합니다.
$ a="one:two:three"
$ echo $a
one:two:three
$ (
> IFS=":"
> echo $a
> )
one two three
$ ( IFS=":"; echo $a )
one two three
하지만아니요:
$ ( IFS=":" echo $a )
one:two:three
이렇게 하려면 명령 실행을 지연해야 합니다.
$ ( IFS=":" eval echo '$a' )
one two three
따라서 스크립트에 대해 다음을 수행해야 합니다.
b="720:500:560:130"
( IFS=":";
for a in $b ;
do echo "$a" ;
done
)
확장은 인용되지 않았기 때문에 $b
모든 glob 문자(*, [, ? 및 extglob 세트가 있는 기타 문자)도 확장됩니다. 어쩌면 하나만 생성하는 대신 파일 목록을 생성할 수도 있습니다.
답변3
IFS의 마법에 맞서 싸우는 대신 Stephen Collyer의 "경로" 기능을 사용하십시오. 콜론으로 구분된 목록이라는 새로운 데이터 유형을 사용할 수 있습니다 bash
. addpath
, delpath
,기다리다. listpath
오프라인 미디어를 검색하고 일반 작업을 수행하기 위해 , 에서 이러한 기능을 사용합니다 .PATH
MANPATH
locate
bash
AskUbuntu에 대한 내 답변은 다음과 같습니다.
나는 2000년에 Linux Journal에 설명된 Stephen Collyer의 bash_path_funcs를 사용합니다.
https://www.linuxjournal.com/article/3645 https://www.linuxjournal.com/article/3768 https://www.linuxjournal.com/article/3935
addpath
이 함수는 처음에 해당 항목이 경로에 존재하지 않는 경우에만 경로에 항목을 추가합니다. delpath -n
경로에서 존재하지 않는 디렉터리를 제거합니다.
pathfunc.tgz
에서 파일을 받을 수 있습니다 .https://web.archive.org/web/20061210054813/http://www.netspinner.co.uk:80/Downloads/pathfunc.tgz