새 파일을 리디렉션하는 cat 명령이 즉시 실행되는 이유는 무엇입니까?

새 파일을 리디렉션하는 cat 명령이 즉시 실행되는 이유는 무엇입니까?

다음과 같이 나중에 호출할 수 있는 bash 파일을 생성하고 싶습니다.

cat <<-SCRIPT >test-$$
        #!/bin/bash
        osType=$(grep -Po '^NAME="\K[^"]*' /etc/os-release)
        if [ "$osType" = ...]
        then
            ...
        fi
        exit
    SCRIPT

디버깅할 때 grep 명령은 항상 올바른 방식으로 실행됩니다. 이유는 무엇입니까? 또한 awk 동일한 오류를 사용해 보았습니다.

하지만 내가 그렇게 한다면

cat <<-SCRIPT >test-$$
        #!/bin/bash
        rpm -q somepackage > test-$$
        rm test-$$-lock
        exit
    SCRIPT

rpm 명령이 올바른 방식으로 실행되는 것을 볼 수 없습니까? test-$$와 test-$$-lock도 동일한 $$를 갖습니까?

답변1

here-doc와 같은 것은 <<-SCRIPT확장이 내부에서 처리되므로 큰따옴표로 묶인 문자열처럼 동작합니다. 이를 방지하려면 구분 기호를 인용하십시오.

$ cat <<EOF
1+1 = $((1+1))
EOF

1+1 = 2

그리고

$ cat <<'EOF'
1+1 = $((1+1))
EOF

1+1 = $((1+1))

그래서 여기 있습니다:

cat <<-SCRIPT >test-$$
        ...
        osType=$(grep -Po '^NAME="\K[^"]*' /etc/os-release)

명령은 grep명령 대체에 있으며 SCRIPT따옴표 없이 처리되므로 여기 문서를 사용할 때 실행됩니다.

반면에 여기에서는:

cat <<-SCRIPT >test-$$
        #!/bin/bash
        rpm -q somepackage > test-$$
        rm test-$$-lock
        exit
    SCRIPT

명령 대체가 없으므로 명령이 실행되지 않습니다. 이 rpm -q somepackage섹션은 텍스트일 뿐입니다. 그러나 따옴표가 없는 구분 기호를 사용하는 경우 $$여기의 문서 내부는 출력 파일 이름에 사용된 것과 동일한 값으로 즉시 확장됩니다. 즉, 현재 쉘의 PID가 1234인 경우 이 명령은 포함 라인을 cat생성합니다 .test-1234rpm -q somepackage > test-1234

따옴표로 묶은 구분 기호를 사용하면 $$그대로 유지되며 결과는 test-1234포함 이라고 합니다 rpm -q somepackage > test-$$. test-1234지금 스크립트로 실행 하면 $$확장되고저것쉘의 PID가 사용됩니다. 파일 생성 시 사용된 값과 다를 수 있습니다.

그럼에도 불구하고 $$rpm .. > test-$$동일한 rm test-$$-lock값으로 확장됩니다.

관련 정보