为什么不能在批处理 for 循环中使用问号? [英] Why can't you use a question mark in a batch for loop?

查看:57
本文介绍了为什么不能在批处理 for 循环中使用问号?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

前言

在编写单独的一段代码时,我遇到了 for 循环中的问号问题.如下图,for循环中没有访问问号.

批处理文件:

@echo off对于 %%x in (the, quick, ?, brown, fox) 做 (回声%%x)

输出:

快的棕色的狐狸

这在 CMD 中也不起作用(使用 %x 而不是 %%x),或者在使用 "" 时、[]^\%或其他常用的字符转义方法.

使用计数器变量来确定访问括号内代码的次数只会导致总计数为 4,这意味着 echo 命令显然没有问题.>


问题

为什么问号在标准 for 循环中不起作用,我该如何解决?

解决方案

这是因为 ? 将被扩展为一个长度为一个字符的文件名列表.裸"for 使用该列表作为文件名列表.

如果您运行以下命令,您将看到此操作:

c:\>回声 xx >ac:\>回声 xx >bc:\>对于 (1, ?) 中的 %i 做 echo %x1一种乙

如果您查看 Rob van der Woude 出色的脚本页面,您会看到 for 页面 有用于处理命令输出、数字和文件的选项 - 它不是非常适合任意字符串.

解决这个问题的一种方法是提供您自己的 for 类似命令,如下例所示:

 @echo offsetlocal enableextensions enabledelayedexpansionrem 为每个参数调用回调函数.设置逃生=/调用 :doFor :processEach 1 2 ?4 5echo.Escapee 是 %escapee%rem 对每个参数执行简单命令.呼叫 :doFor echo 6 7 ?9 10本地端转到:eof:processEach设置逃生者=%逃生者%%1/转到:eof:做设置本地rem 采取行动.设置 cbAction=%1转移:dflooprem 使用回调或命令处理每个参数.如果不是 "%1" == "" (调用 %cbAction% %1转移转到:dfloop)endlocal&&set escapee=%escapee%转到:eof

这提供了一个可以处理回调和简单命令的函数.对于更复杂的命令,提供一个回调函数,它将依次使用每个参数调用.回调函数可以是任意复杂的,但请记住,因为它在 setlocal 中运行,对环境变量的更改无法返回给调用者.

作为一种解决方法,它允许一个变量,escapee,转义范围 - 如果需要,您还可以添加更多.

对于简单的命令(比如 echo),你只需要将参数放在最后,你做同样的事情.它不需要回调函数,但仅限于非常简单的场景.

还要记住,虽然这看起来像很多代码,但其中的绝大多数只需要存在于一个地方.要使用它,您只需要一个像示例一样的单线:

call :doFor echo 我的气垫船装满了鳗鱼

还要记住,即使采用这种方案,也可能存在 其他 字符表现不佳.它解决了 ? 问题,但其他人可能仍然会导致问题.我怀疑这将是将 PowerShell 添加到您的 CV 的理想机会,例如,一个几乎与 bash 类似的命令,它的优雅和禅意:

PShell>foreach ($item in @("1", "?", "3", "4")) { echo $item }1?34

Preface

While writing a separate piece of code, I encountered a problem with question marks in for loops. As shown below, the question mark is not accessed in the for loop.

Batch file:

@echo off

for %%x in (the, quick, ?, brown, fox) do (
    echo %%x
)

Output:

the
quick
brown
fox

This also does not work in the CMD (using %x instead of %%x), or when using "", [], ^, \, % or other common methods of character escaping.

Using a counter variable to determine the number of times the code within the parentheses was accessed only results in a total count of 4, meaning it is clearly not a problem with the echo command.


Question

Why doesn't a question mark work in a standard for loop, and how would I go about fixing it?

解决方案

It's because ? will be expanded into a list of filenames one character long. The "naked" for is using that list as a list of filenames.

If you run the following commands, you'll see this in action:

c:\> echo xx >a
c:\> echo xx >b
c:\> for %i in (1, ?) do echo %x
1
a
b

If you look at Rob van der Woude's excellent scripting pages, you'll see that the for page has options for processing command output, numbers and files - it's not really suited for arbitrary strings.

One way to get around that is to provide your own for-like command as shown in the following example:

    @echo off
    setlocal enableextensions enabledelayedexpansion

    rem Call the callback function for each argument.
    set escapee=/
    call :doFor :processEach 1 2 ? 4 5
    echo.Escapee was %escapee%

    rem Execute simple command for each argument.
    call :doFor echo 6 7 ? 9 10

    endlocal
    goto :eof

:processEach
    set escapee=%escapee%%1/
    goto :eof

:doFor
    setlocal

    rem Get action.
    set cbAction=%1
    shift

:dfloop
    rem Process each argument with callback or command.
    if not "%1" == "" (
        call %cbAction% %1
        shift
        goto :dfloop
    )
    endlocal&&set escapee=%escapee%
    goto :eof

This provides a single functions which can handle both callbacks and simple commands. For more complex commands, provide a callback function and it will get called with each argument in turn. The callback function can be arbitrarily complex but keep in mind that, because it's operating within a setlocal, changes to environment variables cannot escape back to the caller.

As a way around this, it allows one variable, escapee, to escape the scope - you could also add more if needed.

For simple commands (like echo) where you just need the argument placed at the end, you do the same thing. It doesn't need a callback function but it's restricted to very simple scenarios.

Also keep in mind that, although this seems like a lot of code, the vast majority of it only needs to exist in one place. To use it, you simply need a one-liner like the sample:

call :doFor echo my hovercraft is full of eels

Also keep in mind that there may be other characters that do not fare well, even with this scheme. It solves the ? issue but others may still cause problems. I suspect that this would be an ideal opportunity to add PowerShell to your CV, for example, a command that's almost bash-like in it's elegance and zen-ness:

PShell> foreach ($item in @("1", "?", "3", "4")) { echo $item }
1
?
3
4

这篇关于为什么不能在批处理 for 循环中使用问号?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆