다음 오류가 발생합니다.
/tmp/filechecking.sh: line 11: warning: here-document at line 6 delimited by end-of-file (wanted `EOF')
/tmp/filechecking.sh: command substitution: line 8: unexpected EOF while looking for matching `"'
/tmp/filechecking.sh: command substitution: line 11: syntax error: unexpected end of file
/tmp/filechecking.sh: line 6: bad substitution: no closing "`" in `
echo "${filetype[@]}"
done
내 스크립트는
losystem=`ls /appl/vortex/archive/cons/*`
echo "${losystem[@]"
for indsystm in "${losystem[@]}"
do
filetype=`isql -UDAS -PCDRD -SYTRT_DCS_FRET << EOF
select file_type from expected_file where starters_package_version = '4.0' and system_id = 'DAL'
go
EOF`
echo "${filetype[@]}"
done
누구든지 여기서 구문 오류가 무엇인지 도울 수 있습니까?
답변1
losystem=`ls /appl/vortex/archive/cons/*` echo "${losystem[@]" for indsystm in "${losystem[@]}" do filetype=`isql -UDAS -PCDRD -SYTRT_DCS_FRET << EOF select file_type from expected_file where starters_package_version = '4.0' and system_id = 'DAL' go EOF` echo "${filetype[@]}" done
EOF
구문 오류 자체는 다음 과 같은 줄에 나타나는 백틱으로 인해 발생합니다 .코살로난다의 답변. 하지만,스크립트에 다른 문제가 있습니다.따라서 쉘 스크립팅 기술을 더 잘 향상시키기 위해 좀 더 자세히 살펴보겠습니다.
첫 번째 오해: 말씀하신 대로 "${losystem[@]}"
, 당신은배열을 만들었습니다.. 너는 ..하지 않았다. 이렇게 하려면 변수 할당에 괄호를 사용해야 합니다.
마찬가지로, 만약 당신이하다배열을 사용하면 을 사용할 필요가 없습니다 ls
. 구는 배열의 요소로 직접 확장됩니다.
ls
어쨌든 출력을 구문 분석하면 안 되기 때문에 이는 행운입니다.
따라서 변수를 설정하는 올바른 방법 losystem
은대량으로그 요소는 그 안에 있는 파일과 디렉터리입니다 /appl/vortex/archive/cons/
.
losystem=(/appl/vortex/archive/cons/*)
두 번째 줄의 명령 echo
에 종결자가 없습니다 }
.
또한 printf
여기에서 사용할 수도 있습니다.
printf '%s\n' "${losystem[@]}"
또한보십시오:
루프 for
는 Bash 배열의 요소를 반복하는 데 적합 losystem
하므로 위의 수정 사항을 적용한 경우 변경하지 않고 사용할 수 있습니다.
그러나 당신은 그러지 않았습니다.필요어레이 등을 설정하세요.구절(더 깔끔하고 직관적) for 루프에서 직접 파일 glob을 선언합니다.
for indsystem in /appl/vortex/archive/cons/*; do
이는 또한 Bash 배열에 의존하지 않는다는 점에서 POSIX와 호환된다는 장점이 있으므로 더 넓은 범위의 셸에서 작동합니다(즉, 이식성이 더 높습니다).
스크립트의 다음 부분은 filetype
설정하는 것처럼 보이기 때문에 검토하기가 더 어렵습니다.산출명령했는데 isql
넌 안 했어하다인쇄하는 것을 제외한 이 출력의 모든 것(잘못된 형식) echo
. (다시 한번 보세요.왜 printf가 echo보다 나은가요?)
가장 확실한 방법은 변수를 전혀 설정하지 않고 명령을 직접 실행하는 것입니다. 그러면 실제로 원하는 대로 자체 출력이 인쇄됩니다.
isql -UDAS -PCDRD -SYTRT_DCS_FRET << EOF
select file_type from expected_file where starters_package_version = '4.0' and system_id = 'DAL'
go
EOF
알아채다나는 그것에 익숙하지 않기 isql
때문에 이 명령의 정확성을 증명하지 않습니다. 이것은 귀하가 직접 작성한 명령이며 변경된 사항이 없습니다. 정확할 수도 있고 아닐 수도 있습니다.
하지만 이 스크립트의 가장 이상한 점은 배열 indsystem
의 모든 요소를 설정하거나 losystem
그렇게 하려고 한다는 것입니다.당신은 가치를 인용하지 않습니다 "$indsystem"
.
이것은 "방 안의 코끼리"입니다. 나는 당신의 마음을 읽을 수 없기 때문에 이 논리를 고칠 수 없습니다. 무엇을 하고 싶은지 전혀 명확하지 않습니다.
몇 가지 다른 가능성을 생각해 볼 수 있습니다.
isql
어쩌면 디렉토리에 있는 모든 파일에 대해 명령을 실행하려고 할 수도 있습니다cons
. (이 경우isql
명령은 어딘가에 있는 변수를 참조해야 하며indsystem
디렉터리에서 실행하고 있지 않은지 확인해야 합니다.)- 디렉토리가 비어 있지 않은
isql
경우에만 명령을 한 번만 실행하고 싶을 수도 있습니다 .cons
isql
따옴표 없이 명령을 실행 하고 싶을 수도 있지만indsystem
, 디렉토리의 파일/디렉터리와 동일한 방식으로 여러 번 실행하십시오cons
. (이것이 제가 수정한 코드 버전에서 수행할 작업이지만 별 의미가 없습니다.)
이러한 가능성 중 어느 것도 확실히 정확하지 않으므로 스크립트가 실제로 무엇을 하려고 하는지 알 수 없습니다.
그래도 이것이 쉘 스크립팅에 대해 더 많이 배우는 데 도움이 되기를 바랍니다. Bash 스크립팅을 제대로 배우려면 다음을 권장합니다.울위치 카니발 가이드.
나는 또한 내 전문적인 경험을 통해 이 스크립트만큼 많은 문제가 있는 쉘 스크립트에는 일반적으로 아키텍처/디자인 문제가 있다는 것을 발견했다고 말하고 싶습니다.더 높은 수준에서, 그 다음에대개진정으로 실행 가능한 솔루션에 도달하려면 먼저 스크립트가 필요한 이유를 철저하게 검토해야 합니다.
답변2
이 문서의 닫는 구분 기호는 한 줄에 단독으로 표시되어야 합니다.
filetype=`isql -UDAS -PCDRD -SYTRT_DCS_FRET << EOF
select file_type from expected_file where starters_package_version = '4.0' and system_id = 'DAL'
go
EOF
`
$(...)
일반적 으로 새 코드에서는 백틱 대신 백틱을 사용하는 것이 좋습니다. $(...)
중첩 기능이 더 좋고 일반적으로 보기에도 더 좋기 때문입니다.
filetype=$( isql -UDAS -PCDRD -SYTRT_DCS_FRET <<EOF
select file_type
from expected_file
where starters_package_version = '4.0'
and system_id = 'DAL'
go
EOF
)
$(...)
사용하는 것이 더 나은 이유에 대한 자세한 내용은 "*sh 쉘에서는 백틱(예: "cmd")이 더 이상 사용되지 않습니까?"