문서 기본 이름이 충돌합니까?

문서 기본 이름이 충돌합니까?

Rscript를 실행하는 bash 스크립트를 생성하기 위해 EOF를 사용하고 있습니다. Rscript에서는 basename출력 파일 이름을 지정 하는 데 사용합니다 .

bash 스크립트 목록을 생성 하는 데 사용할 때 EOF작동하게 할 수 없습니다 basename. 오류 메시지는 아래와 같습니다. 여전히 bash 스크립트를 생성할 수 있지만 ${AF}나타나는 두 곳 모두 공백으로 표시됩니다. 아주 이상한!

bash 스크립트를 테스트했는데 작동 중이므로 문제 EOFbasename.

basename와 함께 어떻게 사용하나요 EOF? 아니면 대안이 있나요? 감사해요.

for letter in {A..Z}
      do cat <<- EOF > batch_${letter}.sh
    #!/bin/bash
    module load R/3.5.1
    R_func="/home/dir/R_func"
    TREAT="/home/dir/POP"
    BASE="/home/dir/base"
    OUTPUT="/home/dir/tmp"

    for AF in ${BASE}/${letter}*.txt_step3; do
    Rscript ${R_func}P_tools.R \
    --ptool ${R_func}/P_tools_linux \
    --group ${AF} \
    --treat ${TREAT}/pop_exclude24dup \
    --out ${OUTPUT}/OUT_$(basename ${AF%%_txt_step3})_noregress \
    --binary-target F; done

    EOF
       done

오류 메시지입니다.

basename: 피연산자가 누락되었습니다. 자세한 내용은 "basename --help"를 참조하세요.

답변1

구분 기호를 따옴표로 묶지 않으면 명령 대체(예: your $(basename ...)및 변수)도 이 문서에서 확장됩니다. 당신은 그것의 $외부 $(basename ...)뿐만 아니라 $내부의 모든 것에서 탈출해야 합니다.

수정된 스크립트 버전:

for letter in {A..Z}
        do cat <<- EOF > batch_${letter}.sh
                #!/bin/bash
                module load R/3.5.1
                R_func="/home/dir/R_func"
                TREAT="/home/dir/POP"
                BASE="/home/dir/base"
                OUTPUT="/home/dir/tmp"

                for letter in {A..Z} do {
                for AF in \${BASE}/${letter}*.txt_step3; do
                Rscript \${R_func}P_tools.R \
                --ptool \${R_func}/P_tools_linux \
                --group \${AF} \
                --treat \${TREAT}/pop_exclude24dup \
                --out \${OUTPUT}/OUT_\$(basename \${AF%%_txt_step3})_noregress \
                --binary-target F; done
                }
        EOF
done

이것은 실제로 탭으로 들여쓰기입니다. 이 어리석은 웹 인터페이스는 탭을 공백으로 전환하여 <<-POSIX 셸의 상황을 깨뜨릴 수 있습니다. 여기서 문서의 공백과 줄 앞에 있는 EOF 구분 기호가 아니라 탭만 제거합니다.

답변2

<< EOF...여기서 문서라는 구성이 EOF호출됩니다. 원하는 문자열을 구분 기호로 사용할 수 있지만 EOF일반적입니다.

직면한 문제는 여기 문서가 큰따옴표로 묶인 문자열처럼 동작하므로 그 안의 변수 및 명령 대체가 cat런타임 시 확장되고 결과 파일에 있는 그대로 저장되지 않는다는 것입니다. 예를 들어 R_func작성 중인 스크립트에서 설정했지만 batch_x.sh빌드 스크립트의 ${R_func}모든 값 으로 확장되므로 이는 아마도 원하는 것이 아닐 것입니다 .R_func

here-doc 구분 기호를 인용하여 이를 방지할 수 있습니다. 즉 cat << 'EOF', . 그러나 이로 인해 확장이 방지됩니다.모두따라서 파일을 부분적으로 생성하지 않거나 따옴표가 없는 구분 기호를 사용하고 하나의 변수를 제외한 모든 변수를 이스케이프하는 경우 다음과 같은 다른 변수를 확장하지 않고는 파일을 확장할 수 없습니다.빌리 삼촌의 대답.


이제 귀하의 생각을 올바르게 이해했다면 26개의 스크립트를 생성하고 각 문자를 스크립트 중 하나에 하드코딩해야 합니다. 생성한 첫 번째 스크립트( )는 batch_A.sh다음과 같습니다.

module load R/3.5.1
R_func="/home/dir/R_func"
....
for AF in ${BASE}/A*.txt_step3; do
   Rscript ${R_func}P_tools.R \
   ...
done

대신, 아래와 같이 스크립트를 생성하고 문자를 명령줄 인수로 전달할 수 있습니다. 첫 번째 명령줄 인수는 다음과 같이 사용할 수 있습니다 "$1".

#!/bin/bash
module load R/3.5.1
R_func="/home/dir/R_func"
TREAT="/home/dir/POP"
BASE="/home/dir/base"
OUTPUT="/home/dir/tmp"
letter=$1

for AF in ${BASE}/${letter}*.txt_step3; do
    Rscript "${R_func}P_tools.R" \
    --ptool "${R_func}/P_tools_linux" \
    --group "${AF}" \
    --treat "${TREAT}/pop_exclude24dup" \
    --out "${OUTPUT}/OUT_$(basename "${AF%%_txt_step3}")_noregress" \
    --binary-target F;
done

letter이제 명령줄에서 변수를 얻을 수 있으므로 파일 등을 batch.sh A처리하기 위해 실행할 수 있습니다.A

관련 정보