Search code examples
batch-filefor-loopfindstr

batch to scan a file for a string and get the line above in all occurrences, then>output.txt


I have a list.txt file like this little sample:

banana.zip
xxx / yyy / zzz
orange.zip
kkklllmmm
lemon.zip
abc / def / ghi
apple.zip
xxx / yyy / zzz
pineaple.zip
kkklllmmm

I need to filter the .zip lines based on the line below. So, if I choose the string kkklllmmm, the result needs to be:

orange.zip
pineaple.zip

I have started a batch script, but it's incomplete:

@echo off

set "input_list=list.txt"
set "string=kkklllmmm"
set "output_list=output.txt"

for /f "delims=:" %%# in ('findstr /n  /c:"%string%" "%input_list%"') do (
    set "line=%%#"
    set /a "lineBefore=line-1"
    for /f "delims=:" %%a in ("[CONTENT OF %lineBefore%]") do echo %%a>%output_list%)

I would appreciate a help to fix this code and make it work.

Thanks.


Solution

  • to explicate Squashman's suggestion:

    @echo off
    setlocal enabledelayedexpansion
    set "input_list=list.txt"
    set "string=kkklllmmm"
    set "output_list=output.txt"
    
    (for /f "delims=" %%# in (%input_list%) do (
        REM if current line is your searchstring, then echo the previous line:
        if "%%#"=="%string%" echo !line!
        REM set the variable to the current line:
        set "line=%%#"
    )) > "%output_list%"
    

    Note: I used empty delimiter to read the whole line. If you intentionally used : for some reason (aside "some character that isn't in the file to read the whole line"), just reimplement it.

    Edit:

    How did you get the previous line? by setting the line variable after comparing %%#(the current line), so with each turn of the loop at the end line is the current line, but on the next turn at the beginning, it will be the "previous line" (and become the "current line" only at the end of the turn)

    I need to find more than one string: a bit more complicated: add a second for to process each search string. Note the syntax of the set "string=..." line. To also process strings with spaces, this syntax is mandatory. (if there were no spaces, it would simplify to set "string=string1 string2 string3"), but to process the spaces, each substring has to be quoted too:
    set "string="string 1" "string 2" "string 3"")

    @echo off
    setlocal enabledelayedexpansion
    set "input_list=list.txt"
    set "string="kkklllmmm" "xxx / yyy / zzz""
    set "output_list=output.txt"
    (for /f "delims=:" %%# in (%input_list%) do (
        for %%a in (%string%) do (
            echo %%#|findstr /xc:%%a >nul && echo !line!
        )
        set "line=%%#"
    )) > "%output_list%"
    

    The outer for (%%#) gets one line at a time.
    The inner for processes each substring in the list at a time.
    The next line echoes the line and tries to find the substring (switches
    x=compare the complete line,
    c=search for the literal string (including the spaces, else it would try to find each word in the string, e.g. xxx, /, yyy etc.)
    && executes the command echo !line! only, if the previous command succeeded (findstr found a match)