批处理回显管道符号引起意外行为

29

我在批处理文件中有一个变量,其中包含管道符号(即:|),因此当我回显该变量时,会显示关于未识别的内部/外部命令的错误。

我需要一种方法来正确地回显它,或者更好的方法是删除符号之后以及包括符号及其之后的所有内容,以及任何额外的空格。

6个回答

48

在Windows批处理文件中使用时,有几个特殊字符通常必须进行转义。以下是部分列表:< > & | ^ %

转义字符是^。所以要得到字面上的|,你应该这样做:

echo ^|

当特殊字符在一个变量中时,处理起来会有些麻烦。但是,如果你使用特殊语法,你可以像这样替换变量中的字符:

set X=A^|B

REM replace pipe character with underscore
set Y=%X:|=_%

echo %Y%
REM prints "A_B"

2
如果你正在处理来自用户系统的文件系统路径,那么正确地转义包含特殊字符的文件名几乎是不可能的。(文件名可能包含 %、!、^、& 等字符) - Anders
2
需要注意的是,执行^%操作是无效的,对于%es,您需要使用另一个%进行转义(即使用%%)。 - Keen

7

在打印变量之前,您必须转义 | 字符。以下代码会打印 a|b

@echo off

set x=a^|b
echo %x:|=^|%

非常感谢 - 这是问题“可能包含管道的输出变量”的唯一“真正”解决方案 - 实际上,这是一个“安全”脚本应该始终执行的操作... - Simon Sobisch

4
这个问题没有指定操作系统。对于unix系统:

转义它

echo \|

或者用引号括起来
echo "|"

我无法避免它,因为变量来自另一个命令,但引号可以解决问题...为什么我以前没想到呢...现在看看能否将所有不需要的数据删除... - Hintswen
1
将引号放在周围会导致引号被输出。 - Joey
我写这个的时候实际上是想到了Unix,所以它相当失败! - Paul Creasey

1

虽然这是一个老问题,但有一个未提及的解决方案,使用起来更加简单:
延迟扩展

使用延迟扩展的优点在于,任何内容都可以不经修改地使用,根本没有任何问题字符。

set "test=A|B&C,D"E^<F^>G"
setlocal EnableDelayedExpansion
echo !test!

set test       --- Works, but shows also: "test=..."
echo %test% --- This one fails

你的例子对我来说仍然不太有意义,但延迟扩展正是我在寻找的答案。谢谢! - Travis

0
set X=%0^|callset.bat
set Y=%X:|=_%
echo %Y%
echo %X% _ %Y%
REM activate callset | more

REM 这样你应该会有无限的管道。连按两次 CTRL+C 或 Ctrl+Break。 REM 输出 "The process tried to write to a nonexistent pipe."


0

Henrik的回答适用于仅想将变量内容回显到屏幕上的情况,但如果您想将包含管道符号的值传输到另一个程序(就像我所做的那样),则需要添加更多插入符号(^):

回显包含管道符号(|)的裸文本:

echo Hello ^| world

设置并回显包含管道符(|)的变量:

set txt=Hello ^| world
echo %txt:|=^|%

输出包含管道符 (|) 的纯文本 到另一个程序

echo Hello ^^^| world | hexdump

产生:

000000   48 65 6c 6c 6f 20 7c 20 - 77 6f 72 6c 64 20 0a     Hello | world .

将包含管道符 (|) 的变量 传递到另一个程序中 并输出:

set txt=Hello ^| world
echo %txt:|=^^^|% | hexdump

产生:

000000   48 65 6c 6c 6f 20 7c 20 - 77 6f 72 6c 64 20 0a     Hello | world .

(hexdump 只是我用来以十六进制和 ASCII 的形式转储 stdin 的实用程序)。

三个脱字符 (^^^) 需要的原因(据我所知)是因为 CMD 实际上会解析命令行两次:第一次是为了识别它包含一个未转义的管道符号(| hexdump 部分);然后每个部分在执行时都会被处理第二次。

第一次转换将 echo Hello ^^^| world 转换为 echo ^| world(将中间部分读作 ^^,后跟 ^|:一个转义的脱字符和一个转义的管道符号)。当它在执行管道时第二次处理时,“幸存”的脱字符保护了管道符号,使得 Hello | world 被传递到下一个命令。


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