tcsh 스크립트를 디버깅하는 데 도움이 필요합니다. heredocs를 사용합니다. 암호:
<pre_setup> <<EOF1
<setup> <<EOF2
<command>
exit 0
EOF2
exit 0
EOF1
이는 <pre_setup>
사전 설정된 명령(예 wash
: )과 setup
그 이후에 실행되는 일부 설정입니다. 작동하지만 setup
작은따옴표가 포함되면 실패하는 것으로 나타났습니다. 내 설정은 다음과 같습니다.
run_setup -cmd '$SOME_ENV -o outdir'
다음 을 설정 run_setup
하고 $SOME_ENV
실행 $SOME_ENV -o outdir
하십시오.
wash -n group_name <<EOF1
run_setup -cmd '$SOME_ENV -o outdir' <<EOF2
<command>
exit 0
EOF2
exit 0
EOF1
실패하다 SOME_ENV: Undefined variable.
. (또는 ) as를 사용하면 여전히 동일한 오류로 실패하기 때문에 wash
in에서는 문제가 되지 않습니다 . 이는 heredocs가 작동하는 방식과 관련이 있습니다. 어떻게 작동하게 할 수 있나요? 탈출의 문제인가? 이 문서를 어떻게 디버깅할 수 있나요?pre_setup
setenv X 1
cat
pre_setup
run_setup -cmd '$SOME_ENV -o outdir'
또한 쉘에서 실행하면 작동한다는 점도 언급하고 싶습니다 . 아니면 달리기만 pre_setup
하면 setup
됩니다. 그래서 이것은 heredocs와 관련이 있습니다.
편집하다: 따옴표로 묶어 다음과 같이 코드를 분리합니다.
/bin/tcsh <<EOF
$WORK_AREA/script.sh.$1
echo \$status > $WORK_AREA/.$1.result
exit 0
EOF
여기서 $1$는 this가 포함된 스크립트에 대한 입력입니다 heredocs
. 작은따옴표로 묶인 경우 $1
in $WORK_AREA/script.sh.$1
은 비어 있습니다. 그러나 따옴표가 없으면 작동합니다. 왜? 어떻게 해결할 수 있나요?
답변1
일반 here-doc은 변수 등을 확장한다는 점에서 큰따옴표로 묶인 문자열과 약간 비슷합니다.
foo=there
cat <<EOF
hello $foo
EOF
"안녕하세요"를 출력합니다. sh-likes에서는 변수가 정의되지 않은 경우 일반적으로 오류가 발생하지 않고 빈 문자열만 표시됩니다.
인용문은 관련이 없습니다. 작은따옴표가 큰따옴표에서 특별하지 않은 것처럼 여기 문서에서는 특별하지 않습니다. 예를 들어 다음도 확장됩니다 $foo
.echo "hello '$foo'"
확장을 방지하고 싶은 것 같으니 구분 기호를 인용하면 됩니다. 그러나 sh와 유사한 쉘과 (t)csh 사이에는 약간의 차이가 있는 것 같습니다.
sh-like에서는 다음과 같습니다.
foo=there
cat <<'EOF'
hello $foo
EOF
prints hello $foo
, 즉 변수를 확장하려는 시도가 이루어지지 않습니다.
(t)csh에서는 같은 방식으로 닫는 구분 기호를 인용해야 하는 것 같습니다.
foo=there
cat <<'EOF'
hello $foo
'EOF'
이것데비안의 tcsh 매뉴얼 페이지설명하다:
<< word
다음과 동일한 줄이 나올 때까지 쉘 입력을 읽습니다.단어.단어변수, 파일 이름, 명령 대체의 영향을 받지 않으며 각 입력 라인은 다음과 동일합니다.단어이 입력 라인을 대체하기 전에.
\
,"
또는 인용되지 않은'
경우`
단어[, ] 변수 및 명령 대체는 , 및 를\
인용하여 중간 줄에서 수행됩니다 .$
\
`
나는 "최대 한 줄이 동일하다"(및 "교체하기 전에 비교")는 참조가 동일하다는 것을 의미한다고 생각합니다. (이것은 Bash 매뉴얼 페이지에서 말하는 것과 다릅니다: "만약단어따옴표가 붙은 경우 구분 기호는 따옴표를 제거한 결과입니다.단어, [...]".)
두 번째 부분은 POSIX sh와 동일합니다. 여기서 인용된 구분 기호는 문서 텍스트의 확장을 억제합니다.
이 문서에서 셸을 제공하면 모든 변수를 확장할 수 있는 2개의 셸이 제공됩니다. here-doc의 쉘을 빌드한 다음 내부 쉘을 실행하여 읽으십시오. 그들은 변수가 무엇인지에 대해 서로 다른 생각을 가질 수 있습니다. 예를 들어 내부 변수는 기본 스크립트에 대한 인수를 갖지 않습니다. 인용 및 이스케이프 처리에 따라 확장되는 변수가 결정됩니다.
따라서 이것을 실행하면:
#!/usr/bin/tcsh
set foo = outer
echo in outer shell, foo is: $foo
tcsh <<EOF
set foo = inner
echo "not escaped, outer shell expands: $foo"
echo " escaped: inner shell expands: \$foo"
EOF
보이는 내부 껍질
set foo = inner
echo "not escaped, outer shell expands: outer"
echo " escaped: inner shell expands: $foo"
첫 번째는 $foo
이미 확장되어 있으며 백슬래시는 에서 확장됩니다 \$foo
. 대신 이를 사용하면 <<'EOF'
셸이 확장되지 않습니다.
따라서 여기서는 따옴표 없이 사용해야 하며 <<EOF
, 원하는 일에 따라 모든 변수를 개별적으로 이스케이프 처리하거나 처리하지 않도록 주의해야 합니다.