如何解决Bash脚本无法识别现有文件
我必须编写一个简单的bash脚本,该脚本可以编译多个sql脚本,这些脚本可以使用Oracle SQLPlus convention包含对其他sql脚本的递归引用,因此最终结果将只有一个sql文件,包含所有(可能也是递归)引用的下标的所有语句。
我用以下bash代码创建了一个名为oracle-script-compressor.sh的简单脚本:
#!/bin/bash
#
#
function err () {
echo $* > "/dev/stderr"
}
function replace_subscripts_placeholders() {
local PROCESSING_FILENAME=$1
echo "-- processing file $PROCESSING_FILENAME"
while read script_line; do
local script_line_NO_LEAD_SPACE="$(echo -e "${script_line}" | sed -e 's/^[[:space:]]*//')"
if [[ $script_line_NO_LEAD_SPACE == \@\@* ]] ; then
local file_name="./${script_line_NO_LEAD_SPACE#\@\@}"
echo "-- found reference to file $file_name"
echo "-- starting with processing,pwd=$PWD"
# for debug purposes:
ls -la
# but this returns always false:
if [ -f "$file_name" ]; then
# so this part is never started:
. replace_subscripts_placeholders $file_name
else
err_msg="WARNING: Could not find the referenced file $file_name"
echo "-- $err_msg"
err $err_msg
fi
else
echo "$script_line"
fi
done < $PROCESSING_FILENAME
}
if test -z "$1" ; then
err "Usage: oracle-script-compressor.sh {file_name_to_process} [> output_file]"
err " Be aware,if the referenced files within {file_name_to_process} are not specified by absolute paths,you have to start the script from corresponding directory."
err " If the part [> output_file] is omitted,then this script writes to standard output"
err " If the part [>> output_file] is used,then the result will be appended to output_file it it exists before the processing"
else
if [ -f "$1" ]; then
replace_subscripts_placeholders $1
else
echo "file $1 does not exist"
fi
fi
我陷入了一个有趣的问题-似乎在函数replace_subscripts_placeholders()内部,文件检查
if [ -f "$file_name" ]; then
. replace_subscripts_placeholders $file_name
else
err_msg="WARNING: Could not find the referenced file $file_name"
echo "-- $err_msg"
err $err_msg
fi
从不进行递归调用,甚至,即使我删除了if语句并使用正确的引用文件名(确实存在)以递归方式真正调用了该函数,也仍然无法识别出该函数,也没有将其传递到循环中递归调用中引用文件的所有行(然后,找不到错误文件,并且无法执行循环)。
我已经将调试消息添加到脚本中,就像上面在脚本中提到的那样,但是仍然找不到,为什么如果文件位于同一目录中,为什么地狱应该bash找不到文件。脚本放置在
user@mycomputer:/tmp/test$ ls -la
celkem 52
drwxr-xr-x 2 user user 4096 zář 14 21:47 .
drwxrwxrwt 38 root root 36864 zář 14 21:48 ..
-rw-r--r-- 1 user user 51 zář 14 21:45 a.sql
-rw-r--r-- 1 user user 51 zář 14 21:45 b.sql
-rw-r--r-- 1 user user 590 zář 14 21:46 start.sql
user@mycomputer:/tmp/test$
spool output__UpdSch.log
whenever sqlerror exit sql.sqlcode
--
--
PROMPT a.sql - starting
select to_char(current_timestamp,'YYYY-MM-DD HH24:MI:SS.FF3') as START_TIMESTAMP from dual;
@@a.sql
PROMPT a.sql - finished
select to_char(current_timestamp,'YYYY-MM-DD HH24:MI:SS.FF3') as FINISH_TIMESTAMP from dual;
--
--
PROMPT b.sql - starting
select to_char(current_timestamp,'YYYY-MM-DD HH24:MI:SS.FF3') as START_TIMESTAMP from dual;
@@b.sql
PROMPT b.sql - finished
select to_char(current_timestamp,'YYYY-MM-DD HH24:MI:SS.FF3') as FINISH_TIMESTAMP from dual;
--
--
spool off
如果执行脚本,似乎它可以正确解码文件名,但是bash中仍然存在问题-文件存在的测试始终返回false:
user@mycomputer:/tmp/test$ ~/tmp/oracle-script-compressor.sh start.sql
-- processing file start.sql
spool output__UpdSch.log
whenever sqlerror exit sql.sqlcode
--
--
PROMPT a.sql - starting
select to_char(current_timestamp,'YYYY-MM-DD HH24:MI:SS.FF3') as START_TIMESTAMP from dual;
-- found reference to file ./a.sql
-- starting with processing,pwd=/tmp/test
celkem 52
drwxr-xr-x 2 user user 4096 zář 14 21:47 .
drwxrwxrwt 38 root root 36864 zář 14 21:48 ..
-rw-r--r-- 1 user user 51 zář 14 21:45 a.sql
-rw-r--r-- 1 user user 51 zář 14 21:45 b.sql
-rw-r--r-- 1 user user 590 zář 14 21:46 start.sql
-- WARNING: Could not find the referenced file ./a.sql
WARNING: Could not find the referenced file ./a.sql
PROMPT a.sql - finished
select to_char(current_timestamp,'YYYY-MM-DD HH24:MI:SS.FF3') as START_TIMESTAMP from dual;
-- found reference to file ./b.sql
-- starting with processing,pwd=/tmp/test
celkem 52
drwxr-xr-x 2 user user 4096 zář 14 21:47 .
drwxrwxrwt 38 root root 36864 zář 14 21:48 ..
-rw-r--r-- 1 user user 51 zář 14 21:45 a.sql
-rw-r--r-- 1 user user 51 zář 14 21:45 b.sql
-rw-r--r-- 1 user user 590 zář 14 21:46 start.sql
-- WARNING: Could not find the referenced file ./b.sql
WARNING: Could not find the referenced file ./b.sql
PROMPT b.sql - finished
select to_char(current_timestamp,'YYYY-MM-DD HH24:MI:SS.FF3') as FINISH_TIMESTAMP from dual;
--
--
spool off
user@mycomputer:/tmp/test$
该脚本具有对文件的读取权限,所有文件都位于启动该脚本的同一文件夹中,这也没关系,如果我引用当前目录前缀为“ ./”的文件,是否为没找到。有趣的是,脚本启动期间的检查正确通过了,唯一的问题是在函数内进行搜索...我也尝试过在函数前加上“”。没有它,它就没有任何区别。在引用的文件名中也没有尾随空格。。。如果我将函数内部的变量声明为局部变量,也没有区别。 所以我不知道这可能是问题所在,也许我只是看了太久而看不到某些东西-似乎必须是一些琐碎的事情,就像函数是在其他当前目录中启动的一样-(但pwd和ls显示了目录始终是正确的... ???)-任何帮助或指导都将不胜感激。
解决方法
感谢您的评论,这使我想到了解决方案。我发现,此问题与以下事实有关:测试sql文件是在Windows上创建的,因此它们在行尾始终始终带有<CR><LF>
字符。这导致了我发布的原始bash脚本中的事实,脚本行
while read script_line
不仅将行中的给定文件名放入变量中,还将字符@@
@@a.sql
还有<CR>
字符-则变量中的就是值
@@a.sql<CR>
根本找不到文件a.sql
等的原因是什么。当然,该字符是不可见的,因此在我在此处进行的任何调试回显中均未显示该字符-我不得不将$file_name
的内容放在其他一些字符之间,然后才能在回显测试中看到它。我还进行了其他一些更正,最终的工作脚本按以下方式显示,如果有人需要将引用的SQL脚本合并为一个,则可以这样做:
#!/bin/bash
#
#
function err () {
echo $* > "/dev/stderr"
}
function replace_subscripts_placeholders() {
local PROCESSING_FILENAME=$1
echo "-- processing file $PROCESSING_FILENAME"
while read script_line || [ -n "$script_line" ]; do
local script_line_NO_LEAD_SPACE="$(echo -e "${script_line}" | sed -e 's/^[[:space:]]*//' | sed -e 's/^M$//')"
if [[ $script_line_NO_LEAD_SPACE == \@\@* ]] ; then
local file_name="${script_line_NO_LEAD_SPACE#\@\@}"
echo "-- found reference to file $file_name"
if [ -f "$file_name" ]; then
replace_subscripts_placeholders $file_name
else
err_msg="WARNING: Could not find the referenced file $file_name"
echo "-- $err_msg"
err $err_msg
fi
else
echo "$script_line"
fi
done < $PROCESSING_FILENAME
}
if test -z "$1" ; then
err "Usage: oracle-script-compressor.sh {file_name_to_process} [> output_file]"
err " Be aware,if the referenced files within {file_name_to_process} are not specified by absolute paths,you have to start the script from corresponding directory."
err " If the part [> output_file] is omitted,then this script writes to standard output"
err " If the part [>> output_file] is used,then the result will be appended to output_file it it exists before the processing"
else
if [ -f "$1" ]; then
replace_subscripts_placeholders $1
else
echo "file $1 does not exist"
fi
fi
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。