我收到以下错误
/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
,如中所示拘萨罗南达的回答。然而,该脚本还有其他问题,因此,为了更好地提高 shell 脚本编写能力,让我们仔细看看。
第一个误解:正如您所提到的"${losystem[@]}"
,您似乎认为自己有创建了一个数组。你还没有。为此,您需要在变量赋值中使用括号。
同样,如果你做使用数组,不需要使用ls
.球体将直接扩展成为数组的元素。
ls
这是幸运的,因为无论如何你都不应该解析 的输出;看:
所以将变量设置losystem
为的正确方法大批其元素是里面的文件和目录/appl/vortex/archive/cons/
是:
losystem=(/appl/vortex/archive/cons/*)
您的echo
命令(在第二行)缺少结束符}
.
另外,您可能想printf
在这里使用:
printf '%s\n' "${losystem[@]}"
另请参阅:
该for
循环对于迭代 Bash array 的元素是正确的losystem
,因此鉴于您已进行上述更正,您可以不加更改地使用它。
然而,你没有需要设置一个数组,还有更多惯用语(更干净,更直观)在for循环中直接声明文件glob:
for indsystem in /appl/vortex/archive/cons/*; do
这还有一个优点是兼容 POSIX,因为它不依赖于 Bash 数组,因此它可以在更广泛的 shell 中工作(即更便携)。
脚本的下一部分更难以审查,因为看起来您正在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
。 (这就是我的固定版本的代码将要做的事情,但它没有多大意义。)
这些可能性显然都不正确,所以我无法断定脚本实际上想要做什么。
尽管如此,我还是希望这对学习更多有关 shell 脚本的知识有所帮助。要正确学习 Bash 脚本,我推荐伍利奇狂欢指南。
我还要评论说,根据我的专业经验,我发现像这个问题一样多的 shell 脚本通常存在架构/设计问题在更高的水平上, 然后通常有必要首先彻底审查需要该脚本的假定原因,以获得真正可行的解决方案。
答案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 shell 中的反引号(即“cmd”)是否已被弃用?”