批处理文件:逃离问号在for循环

问题描述 投票:2回答:4

for循环(降低的最小例子);

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

扼流圈上的2个元素具有“?”字符。它输出

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

C:\Temp>

所以它只是退出循环,当它击中第一个“?”。

什么是这一套正确的转义序列?尝试了一堆东西,双引号,插入记号,反斜线等,但似乎没有任何工作。

windows batch-file escaping
4个回答
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命令的帮助。


2
投票

似乎没有任何工作,因为任何方法都行不通。

在其最简单的形式(for %%x in (set) do ...),当在该组中的元素的for命令迭代,它将如果该元素包含一个*?测试。在这种情况下,它被认为是一个文件通配符,并且将搜索匹配指定表达式的文件。你可以在你的情况下测试它放置与单个字符名称的文件,并包含批处理文件的文件夹中没有扩展名,而?将匹配它,你会看到它的输出。

而据我所知是没有办法避免。这是命令的目的是在上班的路上。

您可以构建类似于你想什么东西,但需要另一种方法

@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命令的选项进行处理检索。这只是其中的一个选项。你需要的值作为行分隔字符串与for /f进行处理。


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
)

至于原来的问题,也有可用的其他几个选项。亚历克斯是在一些与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/?值。您还可以使用一些其他的字符,如(,但我发现结肠更具可读性。
  • 换行符是允许的,但所有的空格连续(空格和换行符)都用一个空格代替(额外空间可以通过单一的插入符号^逃逸它们执行)。 echo ^&将计为echo不带参数,并显示当前回波设置,echo:^&会给一个空行(FOR / F忽略空线),和echo: ^&会给你
  • qazxsw POI需要三克拉转义。 qazxsw POI需要用一个单一的插入符号进行转义。
  • 没有^ & < > | "选项,你不必逃避` ),但你需要逃跑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:"
  • 同样,没有'选项,您需要使用单引号,而不是周围的反引号的。

-1
投票

如果使用`循环它的工作原理没有逃脱usebackq人物,虽然环不相同的方式工作:

for /f
© www.soinside.com 2019 - 2024. All rights reserved.