Rscript를 실행하는 bash 스크립트를 생성하기 위해 EOF를 사용하고 있습니다. Rscript에서는 basename
출력 파일 이름을 지정 하는 데 사용합니다 .
bash 스크립트 목록을 생성 하는 데 사용할 때 EOF
작동하게 할 수 없습니다 basename
. 오류 메시지는 아래와 같습니다. 여전히 bash 스크립트를 생성할 수 있지만 ${AF}
나타나는 두 곳 모두 공백으로 표시됩니다. 아주 이상한!
bash 스크립트를 테스트했는데 작동 중이므로 문제 EOF
가 basename
.
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