【问题标题】:check "IF" condition inside FOR loop (batch/cmd)检查 FOR 循环内的“IF”条件(批处理/cmd)
【发布时间】:2009-07-22 08:51:04
【问题描述】:

我需要在 Windows 批处理文件中实现的代码是这样的(目前在 Perl 中):

while(<file>)
{
   if($_ =~ m/xxxx/)
   {
      print OUT "xxxx is found";
   }
   elsif($_ =~ m/yyyy/)
   {
      next;
   }
   else
   {
      ($a,$b) = split(/:/,$_);
      $array1[$count] = $a;
      $array2[$count] = $b;
      $count++;
   }
}

我的问题是:

  1. 这种复杂程度在 Windows 批处理文件中是否可行?
  2. 如果是这样,我该如何设置 If 条件 在 for 循环中读取文本 文件?

感谢您的关注。如果您知道答案,或者对如何获得答案有任何想法/线索,请分享。

编辑:我在 Windows 中工作。我只能使用 Windows 默认提供的任何东西,这意味着我不能使用 Unix 实用程序。

【问题讨论】:

  • 首先说明您想要哪种类型的批次。例如,BASH 可以比 NT 的 cmd.exe 做更多和更简单的事情。你的答案决定了问题的答案。
  • 特别是你是在Win32还是UNIX环境下工作?

标签: batch-file


【解决方案1】:

if 放入for 通常很容易:

for ... do (
    if ... (
        ...
    ) else if ... (
        ...
    ) else (
        ...
    )
)

可以使用/f 开关编写循环遍历行的for

for /f "delims=" %%s in (*.txt) do (
    ...
)

正则表达式由findstr 提供。如果没有提供输入文件,它将与stdin 匹配。您可以将输出重定向到NUL,这样它就不会显示找到的字符串,只需使用它的errorlevel 来查看它是否匹配(0 表示匹配,非0 表示不匹配)。您可以再次使用/f 拆分字符串。所以:

set count=0
for /f "delims=" %%s in (foo.txt) do (
    echo %%s | findstr /r xxxx > NUL
    if errorlevel 1 (
        rem ~~~ Didn't match xxxx ~~~
        echo %%s | findstr /r yyyy > NUL
        if errorlevel 1 (
            rem ~~~ Didn't match yyy ~~~
            for /f "delims=; tokens=1,*" %%a in ('echo %%s') do (
                 set array1[!count!]=%%a
                 set array2[!count!]=%%b
                 set /a count+=1
            )
        )
    ) else (
        echo XXX is found
    )
)

【讨论】:

  • Minaev 之所以写 array[!count!] 而不是 array[%count%] 是因为 for 循环中的变量在循环执行后立即展开,所以计数总是在循环期间读为 0。因此,有必要使用延迟变量扩展,以便在读取行时扩展值。无论如何,我的警告也适用于这里:如果文件有像 |& 这样的字符,批处理脚本将会行为不端。
  • 是的,这是在批处理文件中执行此操作的方法。但这必须留给必须维护它的批处理专家。
【解决方案2】:

我认为这在 CMD.EXE 中太痛苦了,甚至完全不可能,尽管我可能在最后一个上弄错了。

您最好使用 WSH(Windows 脚本宿主),它允许您使用 JScript 或 VbScript,并且几乎存在于每个系统中。 (如果需要,您可以提供可再分发的内容)

【讨论】:

  • split,例如,我想基本窗口很难做到。
  • 拆分将使用for /f 完成。语法不完全漂亮,但也不难。
【解决方案3】:

我没有使用 perl 的经验,但如果我正确理解你的命令,它会是这样的。请注意,批处理脚本非常原始,并且没有任何好的清理方法,因此某些字符(主要是 &|)会将其分解成碎片。

@ECHO OFF
SETLOCAL
SET COUNT=0
FOR /F "DELIMS=" %%A IN ('file') DO CALL :SCAN %%A
:SCAN
ECHO %*|FIND "xxxx">NUL
IF %ERRORLEVEL%==0 ECHO xxxx is found&GOTO :EOF
ECHO %*|FIND "yyyy">NUL
IF %ERRORLEVEL%==0 GOTO :EOF
FOR /F "TOKENS=1,2 DELIMS=:" %%A IN ('ECHO %*') DO SET ARRAY1[%COUNT%]=%%A&SET ARRAY2[%COUNT%]=%%B
SET /A COUNT+=1

如果您使用 FINDSTR 而不是 FIND,则可以使用正则表达式。如果您想使用 ARRAY1[%COUNT%] 的值(其中包含一个变量),您必须将“SETLOCAL”替换为“SETLOCAL ENABLEDELAYEDEXPANSION”并使用 !ARRAY1[%COUNT%]!

PS:我没有测试这个脚本,但据我所知它应该可以工作。

【讨论】:

    【解决方案4】:

    这是您的 Perl 脚本的粗略 vbscript 等价物。

    Set objFS = CreateObject("Scripting.FileSystemObject")
    strFile = "c:\test\file.txt"
    Set objFile = objFS.OpenTextFile(strFile)
    Dim array1()
    Dim array2()
    count=0
    Do Until objFile.AtEndOfStream
        strLine = objFile.ReadLine
        If InStr(strLine,"xxxx") >0 Then
            WScript.Echo " xxxx is found."
        Else
            s = Split(strLine,":")
            ReDim Preserve array1(count)
            ReDim Preserve array2(count)
            array1(count)=s(0)
            array2(count)=s(1)
            count=count+1
        End If 
    Loop
    'print out the array elements
    For i=LBound(array1) To UBound(array2)
        WScript.Echo array1(i)
        WScript.Echo array2(i)
    Next
    

    供您参考,总有 Perl for windows 可供您使用,而无需学习另一种语言。

    【讨论】:

    • 您好,感谢您的 VBScript。这似乎是批次的一个很好的选择。至于 windows 上的 perl,是的,我在 windows 中使用 perl。但是我想要批量的代码是给一个客户的,他 - 天知道为什么 - 不想在他的 PC 上安装 perl :-)
    • 您可以安装 Perl2exe 并将您的 Perl 脚本转换为可执行文件以进行分发。
    • -1 用于提供 VBScript 实现而不是 JScript(不,开个玩笑)
    【解决方案5】:

    您可以使用PAR::Packer 将 Perl 程序转换为不需要 perl 的 .exe(甚至可以进行加密)。最好使用Strawberry Perl for Windows 与 PAR::Packer 一起工作,但也可以使用 ActivePerl。

    【讨论】:

      【解决方案6】:

      有可能!

      FOR ................. DO  (
          (YOUR_CONDITION && echo "YES" ) ||  (echo "NO")
      )
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-07-30
        • 2016-12-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-04
        相关资源
        最近更新 更多