9

The code I need to implement in a Windows batch file is like this (it is currently in 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++;
   }
}

How can I put an If condition inside a for loop to read a text file using a batch script file?

I am working in Windows. I can use only whatever is provided with Windows by default and that means I cant use Unix utilities.

0

6 Answers 6

18

Putting if into for in general is easy:

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

A for loop that iterates over lines can be written using /f switch:

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

Regexps are provided by findstr. It will match against stdin if no input file is provided. You can redirect output to NUL so that it doesn't display the found string, and just use its errorlevel to see if it matched or not (0 means match, non-0 means it didn't). And you can split a string using /f again. So:

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
    )
)
Sign up to request clarification or add additional context in comments.

2 Comments

The reason why Minaev writes array[!count!] instead of array[%count%] is because the variables inside a for loop are expanded as soon as the loop is executed, so the count would always be read as 0 during the loop. So, it is necessary to use delayed variable expansion so that the value is expanded whenever the line is read. Anyway, my warning applies here too: if the file has characters like <>|& the batch script will misbehave.
Yes, this is the way to do it in batch file. But this must be reserved to batch experts that will have to maintain it.
2

I think this is too much of a pain to do in CMD.EXE, and even outright impossible, though I may be mistaken on the last one.

You'd better off using WSH (Windows Scripting Host), which allows you to use JScript or VbScript, and is present in pretty much every system. (and you can provide a redistributable if you want)

2 Comments

split, for instance, is very hard to do with basic windows, I imagine.
split would be done with for /f. Not exactly pretty syntax but not exactly hard either.
2

I've no experience with perl, but if I understand your command properly, it would be like this. Beware that batch scripting is very primitive and that it doesn't have any good methods for sanitization, so certain characters (&|<> mostly) will break this into pieces.

@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

If you use FINDSTR instead of FIND you can use regexp. If you want to use the value of ARRAY1[%COUNT%] (with a variable inside it) you'll have to replace "SETLOCAL" with "SETLOCAL ENABLEDELAYEDEXPANSION" and use !ARRAY1[%COUNT%]!

PS: I didn't test this script, but as far as I can tell it should work.

Comments

1

here's a rough vbscript equivalent of your Perl script.

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

For your information, there is always the Perl for windows which you can use, without having to learn another language.

3 Comments

Hi, Thanks for the VBScript. It seems to be a good alternative for the batch. As for perl on windows, yes, I am using perl in windows. But the code that i want in batch is for a customer, who - god knows why- dont want to install perl on his PC :-)
you can install Perl2exe and convert your Perl script to an executable for distribution.
-1 for providing a VBScript implementation instead of JScript (no, just kidding)
0

You can transform Perl program into an .exe that will not need perl with PAR::Packer (even encrypting is possible). Best to use Strawberry Perl for Windows to work with PAR::Packer, but using ActivePerl is also possible.

Comments

0

It's Possible!

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.