【发布时间】:2023-03-13 16:17:02
【问题描述】:
我必须编写一个简单的 bash 脚本,它编译多个 sql 脚本,其中可以包含对其他 sql 脚本的递归引用 Oracle SQLPlus convention,所以最终结果将只有一个 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$
文件 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;
@@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 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;
-- 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 显示目录总是正确的......???) - 任何帮助或指针将不胜感激。
【问题讨论】:
-
欢迎您阅读How to Ask,更重要的是阅读minimal reproducible example。
-
我不知道
if测试(正如@Nic3500 所说,您确实需要删除与问题无关的所有内容——这对于除您以外的其他人进行调试),但我确实看到了另一个问题:不要使用.命令来运行函数,这不是它的作用。.命令在当前 shell 中内联运行命令从脚本文件(非常类似于source命令)。我还建议将set -x放在问题部分之前,以获取 shell 在那里执行的操作的执行跟踪。 -
@GordonDavisson 感谢回复 -
.只是绝望的表达:-)。当然没用过我也试过,没影响。 -
一般来说我很抱歉 - 我认为,这个例子足够小:-) 冗长是由调试消息引起的,这对代码并不重要,但如果重现问题会很有帮助 - 我想,每个想复制它的人都会以类似的方式进行。但是非常感谢您的提示,我会尽量减少冗长的内容。
标签: bash oracle file-exists