As was foretold, we've added advertisements to the forums! If you have questions, or if you encounter any bugs, please visit this thread: https://forums.penny-arcade.com/discussion/240191/forum-advertisement-faq-and-reports-thread/
Options

Learning to write Batch Scripts

jclastjclast Registered User regular
edited August 2013 in Help / Advice Forum
So I'm trying to learn to write batch scripts for work, and this for loop is screwing me up.
First, here are the contents of "file_test.txt":
1 2 3
4 5 6

Second, here are the contents of "test.bat":
@echo off
SetLocal EnableDelayedExpansion
FOR /F "delims=" %%a IN (test_file.txt) DO (
   echo a: %%a
   set b = %a%
   echo b: !b!
)

And this is the results I get:
a: 1 2 3
b: 
a: 4 5 6
b:

What on Earth am I doing wrong?

EDIT: I suppose I should say, this is the results I want:
a: 1 2 3
b: 1 2 3
a: 4 5 6
b: 4 5 6

camo_sig2.png
jclast on

Posts

  • Options
    ArbitraryDescriptorArbitraryDescriptor changed Registered User regular
    edited August 2013
    It's been a while, but I don't think SET works in a DO.

    You can call a subroutine to similar effect:
    
    FOR /F "delims="  %%a IN (test_file.txt) DO ( call :foo %%a)
    GOTO :eof
    
    :foo
     echo a: %1, %2, %3
     set b=%1, %2, %3
     echo b: %b%
    
    
    Drawback there is the subroutine interprets %%a as 3 items (delimited by " "), so you need to know how many args are coming in. Probably a way around that, but like I said: I'm rusty.

    However. If you're just starting, could I suggest you check out Python instead? The syntax isn't much more complicated, and it's a lot more flexible. I used to be all about a nice bat file, but I've moved on and haven't looked back.

    full text of a .py file that does the same thing you're trying to do:
    file = open("test_file.txt","r").read()
    for line in file.split("\n"):
        print("a: "+line)
        b = "b: "+line
        print(b)
    

    the above is Python 3.2

    2.x is a bit different (incompatible), but still widely used. Whichever you choose, if you google up some code and aren't sure which version it is (not usually a problem), check if the print functions use parenthesis:

    print("3.x")
    print "2.x"

    ArbitraryDescriptor on
  • Options
    ArbitraryDescriptorArbitraryDescriptor changed Registered User regular
    edited August 2013
    Tested it. Variables are SET after the FOR/DO is complete. That sounds familiar.
    @echo off
    
    set b=Nostalgia!
    echo Before Loop 1, b = %b%
    FOR %%a IN (one) DO (
    	set b=You haven't changed at all!  That's... cool
    	echo In Loop 1, b = %b%
    )
    echo After Loop 1, b = %b%
    FOR %%a IN (one) DO ( call :foo %%a)
    echo After Loop 2, b = %b%
    
    echo (Spoiler: It was you.)
    GOTO :eof
    
    :foo
     set b=Look batch, it's not you, it's me.  I'm going back to python
     echo In Loop 2, b = %b%
    

    Output:
    Before Loop 1, b = Nostalgia!
    In Loop 1, b = Nostalgia!
    After Loop 1, b = You haven't changed at all! That's... cool
    In Loop 2, b = Look batch, it's not you, it's me. I'm going back to python
    After Loop 2, b = Look batch, it's not you, it's me. I'm going back to python
    (Spoiler: It was you.)

    ArbitraryDescriptor on
  • Options
    Chake99Chake99 Registered User regular
    I'm going to be entirely unhelpful and say if you have any option you might want to consider using perl, python or bash instead of batch.

    Of course if it's for work you quite possibly can't. It's not like I use tcsh everyday because it's what I would freely choose.

    Hic Rhodus, Hic Salta.
  • Options
    jclastjclast Registered User regular
    I may well have the option and already know perl and have done a little python in the past. I think I'll present that today. Thanks, guys!

    camo_sig2.png
  • Options
    AiouaAioua Ora Occidens Ora OptimaRegistered User regular
    Also, if you want to stick strictly vanilla windows you should look into powershell. Most of the command line stuff seems to be getting deprecated anyway. Powershell's the new hotness. Also is pretty good at simple tasks like this:
    Get-Content .\test.txt | ForEach-Object {
        Write-Output "a: $_"
        Write-Output "b: $_"
    }
    

    And condensed!
    gc .\test.txt|%{echo "a: $_";echo "b: $_"}
    

    life's a game that you're bound to lose / like using a hammer to pound in screws
    fuck up once and you break your thumb / if you're happy at all then you're god damn dumb
    that's right we're on a fucked up cruise / God is dead but at least we have booze
    bad things happen, no one knows why / the sun burns out and everyone dies
  • Options
    Sir Headless VIISir Headless VII Registered User regular
    edited August 2013
    fyi what is not working is you don't have the set command properly formatted. It needs to be
    set b=%%a
    
    with no spaces and with %%a instead of %a%.
    @echo off
    SetLocal EnableDelayedExpansion
    FOR /F "delims=" %%a IN (test_file.txt) DO (
       echo a: %%a
       set b=%%a
       echo b: !b!
    )
    
    works for me.

    Sir Headless VII on
    Steam - Backpack - Bnet: SirHeadless #1154
    7KEFduI.jpg
  • Options
    jclastjclast Registered User regular
    Weird. What determines when you need %a% or %%a?

    camo_sig2.png
  • Options
    ArbitraryDescriptorArbitraryDescriptor changed Registered User regular
    edited August 2013
    For loops. (though there may be other cases I'm not aware of)
    @echo off
    SETLOCAL ENABLEDELAYEDEXPANSION
    
    set a=MainA
    
    FOR %%a IN (LoopA) DO (
    	set b=%a%
    	echo !b!
    	set b=%%a
    	echo !b!
    )
    pause
    

    The 'a' you're using in your loop is not the same variable as %a%.
    works for me.
    Oops. I've never used (or seen) '!b!' before, or used delayed expansion. So I guess that's what it does!

    ArbitraryDescriptor on
  • Options
    jclastjclast Registered User regular
    edited August 2013
    Thanks very much for the help. What I'm really coming away from this with, though, is that I should convince my boss that perl would be better. I know that already and it'snot reliant on whitespace (or lack thereof).

    jclast on
    camo_sig2.png
  • Options
    ArbitraryDescriptorArbitraryDescriptor changed Registered User regular
    edited August 2013
    True.

    But it's worth mentioning that the %%a variables in FOR loops actually hold more information than you might think.
    @echo off
    
    for /r %%a in (*.*) do (
    	echo FQ Path: %%~fa
    	echo Filename: %%~na
    	echo Extension: %%~xa
    	echo Path: %%~pa
    	echo Size: %%~za bytes
    	echo -------
            set b=%%a
    )
    echo b = This is just a simple string: %b%
    

    run 'for /?' for a full list if you get shut down on using an alternative to batch.

    ArbitraryDescriptor on
  • Options
    RendRend Registered User regular
    edited August 2013
    jclast wrote: »
    Thanks very much for the help. What I'm really coming away from this with, though, is that I should convince my boss that perl python would be better. I know that already and it'snot reliant on whitespace (or lack thereof).

    Go for python over perl if you can manage it. It's like a billion times more readable!

    Rend on
  • Options
    jclastjclast Registered User regular
    Perl is perfectly readable if you comment and write it like a sane person who learned C first (i.e., me).

    camo_sig2.png
  • Options
    RendRend Registered User regular
    A professor of mine (who is quite proficient in perl) once joked that perl is commonly known as a "write-only" language.

    Not that you should make your decision based on a programming joke, but if you haven't checked out python you definitely should at least take a look at it! Readable as your perl may be, python is quite pretty.

  • Options
    jclastjclast Registered User regular
    I've done a little python, and it is super-readable. White space (or lack of it) being important bothers me though. I'm sure I just cling to perl because I already know it well. It baffles me that it forces indentation so hard that it got rid of braces altogether.

    camo_sig2.png
  • Options
    RendRend Registered User regular
    edited August 2013
    jclast wrote: »
    I've done a little python, and it is super-readable. White space (or lack of it) being important bothers me though. I'm sure I just cling to perl because I already know it well. It baffles me that it forces indentation so hard that it got rid of braces altogether.

    The reason it does that is to actively fight against obfuscated code. It does feel weird not to use braces, especially for a person who primarily uses c-like languages. We share that quality. You just have to think of it this way:

    In every single language, whether you can write a whole app on one line or not, white space is the most important factor there is when readability is concerned. It is one of the only things that just about every programmer will do exactly the same (length of indentation notwithstanding, of course), and the reason is because everyone expects everyone else to have identical indentation.

    In this way, python is not enforcing whitespace, style, or convention, it is enforcing readability.

    Rend on
Sign In or Register to comment.