带有 goto 命令的 Windows 批处理文件不起作用

发布于 2024-09-28 03:52:47 字数 1197 浏览 13 评论 0原文

我对 GOTO 命令和附属标签有疑问。

事实:给定文件夹中的一堆文件(它们是日志错误),我需要打开它们并检查它们是否包含特定字符串。如果是,则从文件名中删除一些字符(最后一次出现“_”之后的所有字符,包括其本身)并执行其他操作。

为了切断字符,我以循环方式使用 GOTO 命令,正如我发现的那样: http:/ /www.robvanderwoude.com/battech_while_loops.php

该脚本是:

@echo off
setlocal EnableDelayedExpansion

cls

for %%X in (D:\e-pub\outbox\logs\*.*) do (

    for /F "tokens=7" %%S in (%%X) do (

        if /i "%%S"=="<ml>" (
            SET fisier=%%~nX
            SET cond=!fisier:~-1!
            SET fisier=!fisier:~0,-1!

            :loopStart
            rem condition to break the loop
            if !cond!==_ goto loopEnd
            SET cond=!fisier:~-1!
            SET fisier=!fisier:~0,-1!
            goto loopStart

            :loopEnd

            rem here it should be out of a loop
            rem other stuff to do with var !fisier!
            rem the following line is not executed because of the label loopEnd
            echo !fisier!
        )
    )
) 

pause

该脚本未运行,因为标签loopEnd后面有一个空行?! 如果我在该标签之后编写任何指令,它们将被执行,但第一个 for 语句的其余迭代将不会被执行(日志错误文件夹包含多个文件)

有人可以提供帮助吗?

I have a problem with GOTO command and affiliated labels.

Facts: Given a bunch of files from a folder (they are log errors) I need to open them and check if they contain a specific string. If yes then eliminate some characters (all the chars after the last appearance of "_", including itself) from the file names and do other operations.

For cutting off the chars I'm using GOTO command in a loop manner as I found it described here: http://www.robvanderwoude.com/battech_while_loops.php

The script is:

@echo off
setlocal EnableDelayedExpansion

cls

for %%X in (D:\e-pub\outbox\logs\*.*) do (

    for /F "tokens=7" %%S in (%%X) do (

        if /i "%%S"=="<ml>" (
            SET fisier=%%~nX
            SET cond=!fisier:~-1!
            SET fisier=!fisier:~0,-1!

            :loopStart
            rem condition to break the loop
            if !cond!==_ goto loopEnd
            SET cond=!fisier:~-1!
            SET fisier=!fisier:~0,-1!
            goto loopStart

            :loopEnd

            rem here it should be out of a loop
            rem other stuff to do with var !fisier!
            rem the following line is not executed because of the label loopEnd
            echo !fisier!
        )
    )
) 

pause

The script is not running because there is an empty line after the label loopEnd?!
If I'm writing any instructions right after that label they will be executed but the rest of iterations from the first for statement won't be executed (the log errors folder contains more one file)

Can someone provide help?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

濫情▎り 2024-10-05 03:52:47

你有两个问题。

一个问题是 goto 破坏了 for 循环。
另一方面,括号中的标签相当困难。

goto 会中断always 和所有嵌套循环,即使goto 的标签位于同一块中,并且for 变量在跳转后立即丢失。

括号中的标签是“两行”导向的!
我尝试了标签,下面是括号的一些结果。

当出现标签时,下一行必须采用正确的“辅助”行格式。

这就是失败的原因。

(
:this label fails with a syntax error
)

(
:this works
:because this line is a "legal" secondary line
)

(
:: The remark style
:: fails, because it's not "legal" to use a double colon, because it's not a legal path (in the most cases)
)

(
:and now I got courious & echo This will not echo'd
:but & echo You can see this !
)

对于第二行,跳过批处理解析器的一些步骤。

@ 不起作用,@echo Hello 尝试启动名为 @echo.bat 的文件。

括号拆分失败,如 echo( hello.
标签作为文件名处理,:echo 仅检查 :echo 是否是有效的文件名,然后跳过这部分。

::hello 在驱动器 :: 上搜索。
出于测试目的,可以使用 subst :: c:\temp 创建驱动器 ::
由于第二行上的标签被忽略,& 符号和管道也可以工作,但 :: 上的文件必须存在。

(
echo @echo This is %~f0
) > %TEMP%\testLabel.bat

REM create Drive ::
subst :: %temp% 
(
:Label 
::\testLabel.bat The bat will not be executed | echo But this
)
subst /D ::

You've got two problems.

One problem is that a goto breaks a for-loop.
The other, labels are quite difficult in parenthesis.

The goto breaks always and all nested loops, even if the label of the goto is in the same block, and the for-variables are lost immediately after the jump.

In parenthesis lables are "two line" oriented!
I experimented with labels and here are some results for parenthesis.

When a label occurs, the next line has to be in the correct format for a "secondary" line.

That's why this fails.

(
:this label fails with a syntax error
)

(
:this works
:because this line is a "legal" secondary line
)

(
:: The remark style
:: fails, because it's not "legal" to use a double colon, because it's not a legal path (in the most cases)
)

(
:and now I got courious & echo This will not echo'd
:but & echo You can see this !
)

For the second line some steps of the batch parser are skipped.

@ doesn't work, @echo Hello tries to start a file named @echo.bat.

Splitting of parenthesis fails, like in echo( hello.
Labels are handeled as a file name, :echo checks only if :echo is a valid file name and then skip this part.

::hello searches on the drive ::.
For test purposes the drive :: can be created with subst :: c:\temp.
As labels are simply ignored on the second line, ampersands and also pipes work, but the file on :: have to exist.

(
echo @echo This is %~f0
) > %TEMP%\testLabel.bat

REM create Drive ::
subst :: %temp% 
(
:Label 
::\testLabel.bat The bat will not be executed | echo But this
)
subst /D ::
在你怀里撒娇 2024-10-05 03:52:47

注释/备注

:: 这是一个 REMark

冒号 (:),实际上是 LABEL 标记,可以通过将其加倍来代替 REM 用于注释 (: :),除了在括号内(即除了在FOR循环内)。

在循环中使用双标签可能会导致批处理脚本失败,但仅当:

  • 双标签后跟下一行的第二双标签
  • 双标签后跟下一行有一个
  • 双标签是循环中的最后一行

换句话说:如果在循环中使用,双标签后面必须跟有包含正常的行(即有效)语法。即使单个标签也是有效的语法。

如果将双标签替换为 REM,则不会出现此错误。

出现双标签错误是因为 CMD.EXE 将 :: 解释为驱动器号(如 C:)。

注意 -
这是对 Jeb 的回答中提到的一个问题的解释,他提出了这一点但没有处理。

Comments / Remarks

:: This is a REMark

A colon (:), which is actually the LABEL tag, can be used for comments instead of REM, by doubling it (::), except within parentheses (i.e. except within a FOR loop).

Using a double-label within a loop can cause the batch script to fail, but ONLY if:

  • The double-label is followed by a second double-label on the next line
  • The double-label is followed by an empty line on the next line
  • The double-label is the last line in the loop

In other words: if used within a loop, the double-label must be followed by a line which contains normal (i.e. valid) syntax. Even a single-label is valid syntax.

This error never occurs if the double-label is replaced with REM.

The error arising from a double-label occurs because CMD.EXE interprets :: as a drive letter (like C:).

.

Note -
This is an explanation for one of the problems mentioned in Jeb's answer, a point which he raises but doesn't deal with.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文