저는 bash 스크립팅에 관한 몇 권의 책을 읽고 있는데 적절한 인용과 IFS
. 아마도 누군가가 따옴표가 있는 파일 이름과 관련된 작은 예를 들어 나를 도울 수 있을 것입니다. 명령줄에서 이 작업을 수행하면 공백이 포함된 경우에도 파일 이름을 올바르게 인쇄할 수 있습니다.
set - *
for i in "$@"; do echo $i; done
공백에서 중단되므로 작동하지 않습니다.
set - `find . -name "*"`
for i in "$@"; do echo $i; done
또한 다음과 같은 경우도 마찬가지입니다.
IFS=$'\0' set - `find . -name "*" -print0`
for i in "$@"; do echo $i; done
IFS=$'\n'
및 를 사용하는 조합도 마찬가지입니다 -print
. 왜 이것들은 모두 실패합니까?
다음도 실패하지만 이 경우 오류가 발생합니다("bash: 예상치 못한 토큰 `do' 근처에 구문 오류가 발생했습니다"). 왜?
IFS=$'\n' for i in `find . -name "*" -type f`; do echo $i; done
하지만 이것은 작동합니다(";"에 주목하세요):
IFS=$'\n'; for i in `find . -name "*" -type f`; do echo $i; done
파일 이름이 전혀 분할되지 않았기 때문에 실패합니다( for
루프는 한 번만).
IFS=''; for i in `find . -name "*" -type f -print0`; do echo -e "$i\n"; done
그렇다면 첫 번째와 세 번째는 왜 실패합니까?
IFS
마지막으로, 설정할 때 가 ''
와 같다는 내 믿음이 맞습니까 $'\0'
? (바로 앞의 예에서 두 가지를 모두 시도했습니다.) 그렇다면 $'\n'
그냥 가 아닌 왜 분명히 필요한가요 \n
?
*Bash는 Ubuntu Gnome 16.04의 버전 4.3.42(1)입니다.
답변1
Bash 명령을 디버깅할 때 배운 두 가지 사항은 다음과 같습니다. 하나) 생각한 대로 작동하지 않으면 명령을 echo/printf하여 생각한 대로 표시되는지 확인하세요. 2) 명령 내에 있는 명령을 수동으로 실행하여 제대로 실행되는지 확인합니다(rm, dd, chmod 777 등과 같이 잠재적으로 파괴적인 명령이 아닌 경우).
정확히 어떻게 또는 무엇을 달성하려고 합니까? 내 명령은 해당 명령을 그대로 사용하면 제대로 작동하는 것 같으므로 원하는 작업을 설명해야 합니다. 파일 이름에 명령에 문제를 일으키는 공백이 있습니까? IFS 변수에서 공백을 제거하는 한 아마도 원하는 대로 작동할 것입니다 IFS=$'\n\t'
. 이 -print0
옵션은 기본적으로 모든 줄 구분 기호를 제거하므로 파일 이름에 공백이 없는 한 해당 명령에서 원하는 모든 항목에는 구분 기호가 전혀 없습니다. 두 번째 질문 세트의 경우:
IFS=$'\n' for i in `find . -name "*" -type f`; do echo $i; done
이 명령은 bash가 다음과 같이 읽기 때문에 제대로 실행되지 않습니다.
IFS=$'\n' for i in `find . -name "*" -type f`
do echo $i
done
첫 번째 줄은 IFS를 다음으로 설정합니다 $'\n' for i in
. 그 후 다음 줄은 다음과 같이 읽습니다. 이는 명령이 이전 명령이 되려면 일종의 루프가 필요하기 do echo $i
때문에 작동하지 않습니다 . do
다음 명령은 세미콜론이 bash에게 명령의 끝에 도달했음을 알려주기 때문에 작동합니다.
IFS=$'\n'
for i in `find . -name "*" -type f`
do echo $i
done
마지막으로 IFS를 설정할 때 ''가 $'\0'과 동일하다는 내 믿음이 맞습니까? (바로 이전 예제에서 두 가지를 모두 시도했습니다.) 그렇다면 \n이 아닌 $'\n'이 필요한 이유는 무엇입니까?
예, 첫 번째 부분은 ''
둘 '\0'
다 NULL로 간주되므로 기본적으로 동일합니다. 이는 bash가 $''
ANSI C 문자열로 해석하기 때문입니다 . 그리고 bash가 이를 C 문자열로 해석하여 개행 문자가 IFS에 배치되도록 하려면 \n 주위에 따옴표가 있어야 합니다.
이에 대한 자세한 내용을 읽을 수 있습니다.여기.