PATH에 개행 문자가 포함될 수 있나요?

PATH에 개행 문자가 포함될 수 있나요?

우리 모두 알고 있듯이 경로에는 모든 구성 요소에 개행 문자가 포함될 수 있습니다.

$PATH그렇다면 환경 변수에 개행 문자가 포함될 수 있다고 결론을 내려야 할까요 ?

$PATH그렇다면 (Bourne like)와 같이 요소로 어떻게 나눌 수 있습니까 ?

    IFS=':' ; set -f
    for var in $PATH
    do
        echo "<$var>"
    done

그러나 IFS를 변경하지 않고 수행할 수 있다면 더 좋을 것입니다.

답변1

POSIX 셸에는 $IFS필드가 있습니다.구분 기호, 구분 기호 대신에 $PATH이와 같은 값은 및 빈 문자열(현재 디렉터리를 나타냄) 대신에 분할 /bin:/usr/bin:됩니다 . 다음을 수행해야 합니다./bin/usr/bin/bin/usr/bin

IFS=:; set -o noglob
for var in $PATH""; do
  printf '<%s>\n' "$var"
done

전역 설정 수정을 방지하려면 명시적인 분할 연산자와 함께 셸을 사용할 수 있습니다 zsh. 예를 들면 다음과 같습니다.

for var in "${(s/:/@)PATH}"; do
  printf '<%s>\n' "$var"
done

이 경우 배열은 zsh이미 $path/ 에 바인딩되어 있으므로 $PATH다음과 같습니다.cshtcsh

for var in "$path[@]"; do
  printf '<%s>\n' "$var"
done

어쨌든, 그렇습니다. 이론적으로 $PATH모든 변수에 개행 문자가 포함될 수 있는 것처럼 개행 문자는 파일 경로 구문 분석에서 특별하지 않습니다. 나는 분별있는 사람이 $PATH이름에 줄 바꿈(또는 와일드카드)이 포함된 디렉토리를 넣거나 줄 바꿈이 포함된 명령 이름을 지정할 것이라고 기대하지 않습니다 . $PATH줄바꿈이 포함되어 있지 않다고 가정하는 스크립트를 누군가가 활용할 수 있는 시나리오도 상상하기 어렵습니다 .

답변2

예, PATH개행 문자를 포함할 수 있습니다(오래된 Unix 시스템에서도 마찬가지입니다).

셸에서 문자열을 분할하는 경우 유일한 이식 가능한 방법은 를 사용하는 것입니다 . 그러나 루프를 사용하는 대신 이를 사용하거나 함수에 전달할 IFS수 있습니다 .IFS=:; set -f; set -- $PATHfor

bash문자열을 "읽을" 수도 있습니다 .대량으로:

xtra=$'some\nother\nplace\n\n'; PATH="$PATH:$xtra"
mapfile -td: path < <(printf %s "$PATH")
printf '<%s>\n' "${path[@]}"

그러나 배열을 사용하는 것은 환경 변수에 투명하게 저장되거나 외부 명령에 단일 인수로 전달될 수 없기 때문에 일반적으로 좋은 생각이 아닙니다.

IFS됩니다 .종료\n필드를 구분하는 대신( 파일을 한 줄씩 읽는 프로그램에서 파일 끝을 빈 줄로 처리하지 않는 것과 비슷함 ), 이것이 예상된 결과가 아니고 실제로 분할할 수 있기를 원하는 경우 문자로 끝나는 문자열 끝에 추가 빈 필드를 만들려면 IFS단어 분할을 원하는 변수 뒤에 빈 문자열을 추가해야 합니다.

(P=/bin:; IFS=:; printf '<%s>\n' $P"")
</bin>
<>

IFS단어 분할 알고리즘은 공백 문자가 문자열의 일부인 경우 문자열 시작 부분의 공백 문자도 무시합니다. 추가 필드를 선행 공백으로 사용하려면 변수 앞에 빈 문자열도 넣어야 합니다.

(P='   foo : bar  '; IFS=': '; set -f; set -- $P; printf '<%s>\n' "$@")
<foo>
<bar>

(P='   foo : bar  '; IFS=': '; set -f; set -- ""$P""; printf '<%s>\n' "$@")
<>
<foo>
<bar>
<>

관련 정보