批处理文件:for循环中的转义问号

时间:2014-05-25 06:26:06

标签: windows batch-file escaping

这个for循环(缩小的最小例子);

@echo off
for %%a in (help -help --help /help ? /?) do ( 
   echo %%a 
)

使用'&'对2个元素进行扼流圈字符。它输出

C:\Temp>test.bat
help
-help
--help
/help

C:\Temp>

所以它只是在它击中第一个'?'时退出循环。

这套装置的正确逃生顺序是什么?尝试了一堆东西,双引号,插入符号,反斜杠等,但似乎没有任何效果。

4 个答案:

答案 0 :(得分:5)

另一种选择是在FOR / F字符串中使用换行符。 FOR / F会将每一行视为一个独立的字符串。下面我展示了四种做同样事情的方法。

@echo off
setlocal enableDelayedExpansion

:: Define LF to contain a linefeed character
set ^"LF=^

^" The above empty line is critical. DO NOT REMOVE

:: Option 1
:: Embed linefeeds directly in the string literal
for /f %%A in ("help!LF!-help!LF!--help!LF!/help!LF!?!LF!/?") do (
  echo(%%A
)


echo(
:: Option 2
:: Define a variable with spaces and use search and replace
:: to substitue linefeeds
set "help=help -help --help /help ? /?"
for %%L in ("!LF!") do for /f %%A in ("!help: =%%~L!") do (
  echo(%%A
)


echo(
:: Option 3
:: Embed linefeed directly in string without LF variable
for /f %%A in (^"help^

-help^

--help^

/help^

?^

/?^") do (
  echo(%%A
)


echo(
:: Option 4
:: Embed linefeed directly in search and replace without LF variable
for /f %%A in (^"!help:^ ^=^

!^") do (
  echo(%%A
)

我更喜欢选项2.我发现它是最容易阅读的,但仍然是紧凑的。

请注意,MC ND和我都使用echo(%%A。这是防止echo /?显示ECHO命令帮助所必需的。

答案 1 :(得分:2)

似乎什么都行不通,因为什么都行不通。

以最简单的形式(for %%x in (set) do ...),当for命令迭代集合中的元素时,它将测试元素是否包含*或{{1} }。在这种情况下,它被视为文件通配符,并将搜索与指示的表达式匹配的文件。你可以在你的情况下测试它,在包含批处理文件的文件夹中放置一个带有单个字符名称且没有扩展名的文件,?将匹配它,你将在输出中看到它。

据我所知,没有办法避免它。这是命令的工作方式。

你可以构建类似于你正在尝试的东西但需要另一种方法

?

在此示例中,每个值都在一个环境变量中,并通过@echo off setlocal set "opt.a=help" set "opt.b=-help" set "opt.c=--help" set "opt.d=/help" set "opt.e=?" set "opt.f=/?" for /f "tokens=2 delims==" %%a in ('set opt.') do ( echo(%%a ) endlocal 命令检索该集合,并使用set命令的选项处理输出。这只是一个选择。您需要将值作为行分隔的字符串来处理for

答案 2 :(得分:0)

虽然我个人认为dbenham提供了最好的answer,但我想补充一点,在某些情况下,应该为FOR / F循环提供选项:

  1. tokens=*-这将禁用行的标记化(或者,如果需要,可以将delims设置为所需的任意值),从而允许在字符串中留有空格;
  2. usebackq-这将允许您在字符串中使用双引号。但是,在这种情况下,单引号必须用脱字号-^'进行转义,并且周围的双引号应替换为单引号:
(set RN=^
%= \r\n =%
)
for /f "usebackq tokens=*" %%A in ('^'quotes^'!RN!"double quotes"!RN!`backquotes`') do (
  echo:%%A
)

对于最初的问题,几乎没有其他选择。 Alex使用his answer进行操作,但是没有涉及如何实际遍历列表。为此,您需要链接回显命令。您从echo:开始,然后使用^&echo:回显所有后续的字符串/变量:

set "var=line1"
for /F "usebackq delims=" %%G in (`
echo:%var%^&
echo:   line2 * ? ^^^^ ^^^& ^^^< ^^^> ^^^| ^^^" ' ^` ^)   ^&
echo: ^ ^ line3 ^ ^ ^&echo:li

ne4^&echo  ^&echo: ^&echo:/?
`) do (
    echo "%%G"
)

这将为您提供:

"line1"
" line2 * ? ^ & < > | " ' ` ) "
"   line3   "
"li ne4"
"ECHO is on."  # System language specific
" "
"/? "
  • 如图所示,只要保持^&echo:完整(请注意空格),就可以以任何方式断开换行。
  • echo之后使用冒号代替空格将清除ONOFF/?之类的值。您还可以使用其他一些字符,例如(,但我发现冒号更具可读性。
  • 允许使用换行符,但是所有连续的空格(空格和换行符)都将替换为一个空格(可以通过使用单个插入符号{{1}对其进行转义来强制执行其他空格)。 ^将算作echo ^&,不带任何参数,并显示当前回显设置,echo将给出一个空行(FOR / F忽略空行),而echo:^&将给出您echo: ^&
  • 需要通过三个插入符进行转义。 ^ & < > | "需要使用单个插入符进行转义。
  • 没有` )选项,您不必逃脱usebackq,但是您需要通过三个插入符逃脱`。您还需要使用单引号而不是反引号。

如果将表达式放在双引号中,则可以避免过度转义:

'

这将为您提供:

for /f "usebackq delims=" %%G in (`"echo:%var%&echo:   line2 * ? ^^ ^& ^< ^> ^| ' ` "abc" ^)   &echo &echo: &echo:/?"`) do (
    echo "%%G"
)
  • 要链接回显命令,请使用"line1" " line2 * ? ^ & < > | ' ` "abc" ) " "ECHO is on." # System language specific " " "/?" (注意,不要插入符号)。
  • 不允许使用换行符。保留了空间。
  • &echo:无法转义,但如果它们的数量为偶数,则可以使用。您不需要逃脱"'
  • 同样,如果没有`选项,您将需要使用单引号而不是反引号。

答案 3 :(得分:-1)

如果你使用for /f循环,它可以在不转义?个字符的情况下工作,虽然循环不会以相同的方式工作:

C:\Users\Alex\Downloads\test>for /f "tokens=* delims=" %a in ('echo help -help --help /help ? /?') do echo %a

C:\Users\Alex\Downloads\test>echo help -help --help /help ? /?
help -help --help /help ? /?