需要将带有换行符的字符串从 Unix shell 脚本传递到 sql 查询
Need to pass string with newline character from Unix shell script to sql query
我正在使用 unix shell KSH 脚本来做一些 table 清理工作。
我有一个文件 "partner.txt" 有 5000 行,像这样
>cat partner.txt
aaa0000
aaa0001
aaa0002
...
...
aaa5000
使用这个文件,我应该清理几个 tables 与匹配,比如合作伙伴的协议。
因此,我正在构建一个合作伙伴列表字符串,其格式可以在 sql 语句中使用 'IN' 子句(select * from tab where partner IN partner_list)
('aaa0000',
'aaa0001','aaa0002',...,'aaa0010',
'aaa0011','aaa0012',...,'aaa0020',
...
'aaa4990','aaa4991',...,'aaa5000')
我像这样将字符串分配给 partner_list 变量。
export BO="("
export BC=")"
export BQ="('"
export QC="','"
export QB="')"
export C=","
export CE=","'\n'
export QCE="',"'\n'"'"
partnerListLine=${BO}
while read partnerline;
do
if [ `expr ${counter} % 10` -eq 0 ]
then
partnerListLine=${partnerListLine}${partnerline}${CE}
elif [ ${counter} -lt ${numOfObsoletePartner} ]
then
partnerListLine=${partnerListLine}${partnerline}${C}
fi
counter=`expr ${counter} + 1`
done < partner.txt
partnerListLine=${partnerListLine}${partnerline}${BC}
然后我使用这个合作伙伴列表来获取我的协议列表,例如
SQL_agreement='select distinct a.agreement from partner_agreement_map a where a.partner in ${partner_list} order by agreement asc;'
我需要在合作伙伴列表中添加换行符,因为我使用的是 sqlplus 并遇到 SP2-0027:输入太长(> 2499 个字符)
我通过在 N partners
之后将以下内容附加到我的合作伙伴列表字符串来添加换行符
CE=","'\n'
当我在脚本中直接使用 sqlplus 时,这工作正常。
但是当我尝试将此 partner_list 字符串作为参数传递给 sql 脚本时,它在查询中显示“\n”。
这就是我调用 sql 脚本并传递参数的方式
sqlplus -s ${REFERENCE_DB_USER}/${REFERENCE_DB_PASS}@${DATABASE_INSTANCE} << !!
set serveroutput on size 10000;
set feedback off;
set verify off;
set echo off;
set term off;
set pagesize 0;
SET linesize 1000;
SET TRIMSPOOL ON;
spool 1_del_agreement_spool_$$.lst;
@1_del_agreement.sql ${partner_list};
spool off;
exit;
/
!!
这是我的假脱机文件
>cat 1_del_agreement_spool_18165.lst <
select distinct a.agreement from partner_agreement_map a where a.partner in ('aaa0000',\n'aaa0001','aaa0002','aaa0003',...'aaa0010',\n'aaa0011'...) order by agreement asc
*
ERROR at line 1:
ORA-00907: missing right parenthesis
当我将参数传递给 sql 脚本而不将其替换为 '\n' 时,如何保持换行符?
我试过 ANSI-C 引用但失败了。
如果您需要 shell 或 sql 脚本的更多详细信息,请告诉我
如果您使用的是 bash,您可以使用 $'\n' 来打印换行符,这将使您的示例成为
if [ `expr ${counter} % 10` -eq 0 ]
then
partnerListLine=${partnerListLine}${partnerline}"',"$'\n'"'"
else
...
示例:
$ echo hello"',"$'\n'"'"
hello',
'
我没有可行的解决方案,但提示:'\n'
表示 "insert the literal backslash followed by n
"。所以你告诉 shell 不要管这个字符串。
尝试 NL=$(echo -e '\n')
或类似的方法来获取实际上包含换行符的字符串变量。然后你可以定义CE=",$NL"
shell 可能会在处理字符串时保留这个换行符。
或者使用像 awk
这样的工具来创建一个带换行符的字符串值,你用 partner_list=$(awk ...)
分配给 partner_list
以防止 shell 做任何类型的值的处理。
如果这不起作用,您可能必须将数据写入文件(使用新行)。
更新了我的整个解决方案设计
试了一晚上,我放弃了。
感谢 Aaron 和 mplf 的投入。
我决定将我的解决方案从基于文件更改为基于table。我将读取 partner.txt 文件并将合作伙伴插入虚拟临时文件 table。然后我可以轻松地对其他 table 进行查询。
事实上,我认为这应该是我的第一个设计:) 在之前的设计中我可能遗漏了一些非常小的东西。但无论如何,这会容易得多
我希望我的团队领导审查设计而不是代码格式问题 :P
我正在使用 unix shell KSH 脚本来做一些 table 清理工作。 我有一个文件 "partner.txt" 有 5000 行,像这样
>cat partner.txt
aaa0000
aaa0001
aaa0002
...
...
aaa5000
使用这个文件,我应该清理几个 tables 与匹配,比如合作伙伴的协议。 因此,我正在构建一个合作伙伴列表字符串,其格式可以在 sql 语句中使用 'IN' 子句(select * from tab where partner IN partner_list)
('aaa0000',
'aaa0001','aaa0002',...,'aaa0010',
'aaa0011','aaa0012',...,'aaa0020',
...
'aaa4990','aaa4991',...,'aaa5000')
我像这样将字符串分配给 partner_list 变量。
export BO="("
export BC=")"
export BQ="('"
export QC="','"
export QB="')"
export C=","
export CE=","'\n'
export QCE="',"'\n'"'"
partnerListLine=${BO}
while read partnerline;
do
if [ `expr ${counter} % 10` -eq 0 ]
then
partnerListLine=${partnerListLine}${partnerline}${CE}
elif [ ${counter} -lt ${numOfObsoletePartner} ]
then
partnerListLine=${partnerListLine}${partnerline}${C}
fi
counter=`expr ${counter} + 1`
done < partner.txt
partnerListLine=${partnerListLine}${partnerline}${BC}
然后我使用这个合作伙伴列表来获取我的协议列表,例如
SQL_agreement='select distinct a.agreement from partner_agreement_map a where a.partner in ${partner_list} order by agreement asc;'
我需要在合作伙伴列表中添加换行符,因为我使用的是 sqlplus 并遇到 SP2-0027:输入太长(> 2499 个字符) 我通过在 N partners
之后将以下内容附加到我的合作伙伴列表字符串来添加换行符CE=","'\n'
当我在脚本中直接使用 sqlplus 时,这工作正常。
但是当我尝试将此 partner_list 字符串作为参数传递给 sql 脚本时,它在查询中显示“\n”。
这就是我调用 sql 脚本并传递参数的方式
sqlplus -s ${REFERENCE_DB_USER}/${REFERENCE_DB_PASS}@${DATABASE_INSTANCE} << !!
set serveroutput on size 10000;
set feedback off;
set verify off;
set echo off;
set term off;
set pagesize 0;
SET linesize 1000;
SET TRIMSPOOL ON;
spool 1_del_agreement_spool_$$.lst;
@1_del_agreement.sql ${partner_list};
spool off;
exit;
/
!!
这是我的假脱机文件
>cat 1_del_agreement_spool_18165.lst <
select distinct a.agreement from partner_agreement_map a where a.partner in ('aaa0000',\n'aaa0001','aaa0002','aaa0003',...'aaa0010',\n'aaa0011'...) order by agreement asc
*
ERROR at line 1:
ORA-00907: missing right parenthesis
当我将参数传递给 sql 脚本而不将其替换为 '\n' 时,如何保持换行符? 我试过 ANSI-C 引用但失败了。
如果您需要 shell 或 sql 脚本的更多详细信息,请告诉我
如果您使用的是 bash,您可以使用 $'\n' 来打印换行符,这将使您的示例成为
if [ `expr ${counter} % 10` -eq 0 ]
then
partnerListLine=${partnerListLine}${partnerline}"',"$'\n'"'"
else
...
示例:
$ echo hello"',"$'\n'"'"
hello',
'
我没有可行的解决方案,但提示:'\n'
表示 "insert the literal backslash followed by n
"。所以你告诉 shell 不要管这个字符串。
尝试 NL=$(echo -e '\n')
或类似的方法来获取实际上包含换行符的字符串变量。然后你可以定义CE=",$NL"
shell 可能会在处理字符串时保留这个换行符。
或者使用像 awk
这样的工具来创建一个带换行符的字符串值,你用 partner_list=$(awk ...)
分配给 partner_list
以防止 shell 做任何类型的值的处理。
如果这不起作用,您可能必须将数据写入文件(使用新行)。
更新了我的整个解决方案设计
试了一晚上,我放弃了。 感谢 Aaron 和 mplf 的投入。
我决定将我的解决方案从基于文件更改为基于table。我将读取 partner.txt 文件并将合作伙伴插入虚拟临时文件 table。然后我可以轻松地对其他 table 进行查询。
事实上,我认为这应该是我的第一个设计:) 在之前的设计中我可能遗漏了一些非常小的东西。但无论如何,这会容易得多 我希望我的团队领导审查设计而不是代码格式问题 :P