提问人:Christian Bongiorno 提问时间:9/6/2023 最后编辑:Christian Bongiorno 更新时间:9/6/2023 访问量:45
如何将 sqlplus 与 heredoc 和文件替换参数一起使用
How to use sqlplus with a heredoc and file substitution args
问:
因此,我试图通过将要执行的脚本包装在“页眉”和“页脚”中来将一些默认配置应用于每次调用,以便获得一致的执行。sqlplus
但是,当我实现这个 bash 函数时,我意识到某些脚本具有参数,当我尝试在使用 heredoc 进行“包装”时将它们传递给时,sqlplus 感到困惑并认为用于替换的参数对它来说是实际的 (sqlplus)。sqlplus
那么,除了创建临时文件之外,有没有办法仍然使用 heredoc(或任何 stdin 流)和脚本参数?envsubst
下面的代码(将其源在文件中,或者简单地将函数复制并粘贴到交互式 shell 中):
function exec_sql_file(){
local sql_file=${1:?You must supply and sql_file file to execute}
local script_dir username password
script_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
source "${script_dir}/omc.env"
local script="${script_dir}/sql/${sql_file}"
sqlplus -s "$username/$password@sredb1_high" <<-EOF "${@:2}" | tail -n "+$#"
set heading off;
set feedback off;
set linesize 10000;
set newpage NONE;
set colsep '|'
$(cat "${script}")
exit;
EOF
} && export -f exec_sql_file
example.sql:
select &1 + &2 from dual
预期用途:
exec_sql_file queries/example.sql 1 3
4
需要的是heredoc之后"${@:2}"
它尝试执行的名义 CLI 是:
sqlplus -s "$username/$password@sredb1_high" @sql/queries/example.sql 1 3
这是一个带有临时文件的工作功能示例(不是我的偏好)
function exec_sql_file(){
local sql_file=${1:?You must supply and sql_file file to execute}
local script_dir username password
script_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
local env_file="${script_dir}/omc.env"
source "${script_dir}/omc.env"
local script="${script_dir}/sql/${sql_file}"
local tmpFile
tmpFile=$(mktemp)
cat <<-EOF > "${tmpFile}"
set heading off;
set feedback off;
set linesize 10000;
set newpage NONE;
set colsep '|'
$(cat "${script}")
exit;
EOF
echo exit | sqlplus -s "$username/$password@sredb1_high" "@${tmpFile}" "${@:2}" |
tail -n "+$#" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'
} && export -f exec_sql_file
答:
1赞
2 revsCharles Duffy
#1
heredoc 更改了 stdin 的定向位置。它不会充当命令行参数或变成命令行参数,因此将参数放在 heredoc 之后(或在此之前)的想法没有任何意义:heredocs 不参与命令行参数排序。
我怀疑你可能想要这样的东西:
buildArgs() {
printf '%s\n' \
'set heading off;' \
'set feedback off;' \
'set linesize 10000;' \
'set newpage NONE;' \
"set colsep '|'" \
cat -- "$script"
printf '%s\n' \
'exit'
}
sqlplus -s "$username/$password@sredb1_high" "@"<(buildArgs) "${@:2}" |
tail -n "+$#" |
sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'
...where 是(在 Linux 上 - 这因平台而异)被 shell 替换为类似 的东西,其中 是可以读取输出的文件名。"@"<(buildArgs)
@/dev/fd/63
/dev/fd/63
buildArgs
(请注意,这是一个 FIFO,所以它只能读取一次;如果你需要它是可查找的,这需要一个单独的解决方案;zsh 有 形式的内置语法,但据我所知,这个功能目前在 bash 中并不可用)。=(buildArgs)
评论
0赞
Christian Bongiorno
9/7/2023
这实际上与临时文件不同吗,因为它创建了?我的意思是,我不必管理它,但你确实给了我一些其他的想法/dev/fd/xx
0赞
Charles Duffy
9/7/2023
@ChristianBongiorno,不是真正的文件系统;所有打开的文件描述符都存在在那里。在实践中,在 Linux 上,它是一个链接,就像所有 procfs 一样,它是完全合成的。因此:指你的 stdin,指你的 stdout,指你的 stderr;如果您调用并返回 FD 3,则会自动出现 .事实上,在 Linux 上,如果你 ,你会引用 或 的东西,它们最终都是一回事。/dev/fd
/proc/self/fd
/dev/fd/0
/dev/fd/1
/dev/fd/2
open()
/dev/fd/3
ls -l /dev/stdout
/dev/fd/1
/proc/self/fd/1
评论
#!/bin/bash
"${@:2}"
EOF
<<-EOF