如何在批处理文件中输出特殊字符?

3

我想将以下查询传递给sqlplus命令。

select 'Version ID:   ' || a1.BACKUP_VERSION  || CHR(13) || CHR(10)||'Status:  ' || a1.STORAGE_STATUS ||  CHR(13) || CHR(10)|| 'Distribution ID:  ' || a1.DISTRIBUTION_ID FROM epc1_distrib_version a1;
当我使用插入符号^在屏幕上回显时,它能正常工作。
echo select 'Version ID:   ' ^|^| a1.BACKUP_VERSION  ^|^| CHR(13) ^|^| CHR(10)^|^|'Status:  ' ^|^| a1.STORAGE_STATUS ^|^|  CHR(13) ^|^| CHR(10)^|^| 'Distribution ID:  ' ^|^| a1.DISTRIBUTION_ID FROM epc1_distrib_version a1;

它显示了正确的查询字符串。但是当我在批处理文件中使用时,它无法正常工作。这是我尝试运行的代码:

@ECHO OFF
echo Connecting to Database...
echo +++++++++++++++++++++++++
(
echo user/pass@instance
echo select 'Version ID:   ' ^|^| a1.BACKUP_VERSION  ^|^| CHR(13) ^|^| CHR(10)^|^|'Status:  ' ^|^| a1.STORAGE_STATUS ^|^|  CHR(13) ^|^| CHR(10)^|^| 'Distribution ID:  ' ^|^| a1.DISTRIBUTION_ID FROM epc1_distrib_version a1;
)| sqlplus -s
echo +++++++++++++++++++++++++

它只显示这个:
Connecting to Database...
+++++++++++++++++++++++++
user/pass@instance
select 'Version ID:   ' || a1.BACKUP_VERSION  || CHR(13
+++++++++++++++++++++++++
它没有将查询传递给 sqlplus 命令,该怎么办?
2个回答

3

您需要转义右括号,例如^)。您的echo命令位于一对括号()之间的代码块中; 任何未转义的右括号都会被解释为该块的结尾。所以修改后的代码如下:

echo select 'Version ID:   ' ^|^| a1.BACKUP_VERSION  ^|^| CHR^(13^) ^|^| CHR^(10^)^|^|'Status:  ' ^|^| a1.STORAGE_STATUS ^|^|  CHR^(13^) ^|^| CHR^(10^)^|^| 'Distribution ID:  ' ^|^| a1.DISTRIBUTION_ID FROM epc1_distrib_version a1;

我省略了开括号^(,虽然这并非必须的,但是为了代码的可读性,这样做能够清楚地表明哪些括号是功能性的,哪些是修饰用的。

在批处理脚本中,您使用管道符|将输出传递给sqlplus命令;这需要进行双重转义,如下所示:

@echo off
echo Connecting to Database...
echo +++++++++++++++++++++++++
(
echo user/pass@instance
echo select 'Version ID:   ' ^^^|^^^| a1.BACKUP_VERSION  ^^^|^^^| CHR^^^(13^^^) ^^^|^^^| CHR^^^(10^^^)^^^|^^^|'Status:  ' ^^^|^^^| a1.STORAGE_STATUS ^^^|^^^|  CHR^^^(13^^^) ^^^|^^^| CHR^^^(10^^^)^^^|^^^| 'Distribution ID:  ' ^^^|^^^| a1.DISTRIBUTION_ID FROM epc1_distrib_version a1;
) | sqlplus -s
echo +++++++++++++++++++++++++

这是因为管道 | 会为每个侧面创建一个新的命令提示符实例,在执行代码部分时,需要将特殊字符隐藏在主命令提示符实例中,从批处理文件所在的实例和由管道进程创建的实例中形成。
另一种选择是将要输出的字符串放置在一对双引号 "" 中(假设该字符串本身不包含这样的字符)。但是,不能使用类似 echo "..." 的命令行,因为输出中包含了 "",我们不想要这些内容。
一个技巧是使用 set /P 命令,该命令用于提示用户输入环境变量的值。我们不需要此处的变量 (#),只需需要提示文本:
set /P "#=select 'Version ID:   ' || a1.BACKUP_VERSION  || CHR(13) || CHR(10)||'Status:  ' || a1.STORAGE_STATUS ||  CHR(13) || CHR(10)|| 'Distribution ID:  ' || a1.DISTRIBUTION_ID FROM epc1_distrib_version a1;"

为了避免该命令等待用户输入,我们将一个echo管道传入其中(只需一个单独的_字符):
echo _| set /P "#=select 'Version ID:   ' || a1.BACKUP_VERSION  || CHR(13) || CHR(10)||'Status:  ' || a1.STORAGE_STATUS ||  CHR(13) || CHR(10)|| 'Distribution ID:  ' || a1.DISTRIBUTION_ID FROM epc1_distrib_version a1;"

最后,让我们在批处理脚本中使用所有这些内容:
@echo off
echo Connecting to Database...
echo +++++++++++++++++++++++++
(
echo user/pass@instance
echo _| set /P "#=select 'Version ID:   ' || a1.BACKUP_VERSION  || CHR(13) || CHR(10)||'Status:  ' || a1.STORAGE_STATUS ||  CHR(13) || CHR(10)|| 'Distribution ID:  ' || a1.DISTRIBUTION_ID FROM epc1_distrib_version a1;"
echo/
) | sqlplus -s
echo +++++++++++++++++++++++++

set /P命令输出的文本不像echo命令那样以最后一行换行符结束。所以我插入了echo/这一行,用于输出一个单独的换行符。


1
它可以工作,但只有在没有管道“|”的情况下才能工作,我忘记了,抱歉;请查看我的编辑... - aschipfl
1
我刚刚添加了一种使用 set /P"" 的替代方法;这样可以避免需要(双重)转义... - aschipfl

2

你可以使用插入符号,但是当你想要将其传输时,就需要两次转义每个特殊字符,并且用引号括起来会很麻烦。

你可以使用延迟扩展来避免这种情况。

set "sql=select 'Version ID:   ' || a1.BACKUP_VERSION  || CHR(13) || CHR(10)||'Status:  ' || a1.STORAGE_STATUS ||  CHR(13) || CHR(10)|| 'Distribution ID:  ' || a1.DISTRIBUTION_ID FROM epc1_distrib_version a1;"

(
  echo user/pass@instance
  cmd /v:on /c "echo ^!sql^!"
) | sqlplus -s

顺便提一下,为了测试您的转义,您可以将sqlplus替换为more以查看您实际回显的内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接