0

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.

Daniel Sian
  • 87
  • 1
  • 10
  • 3
    Don't filter the text file with findstr. Read the entire file and keep the previous line assigned to a variable. When the current line equals your string, then output the previous line. – Squashman Jun 05 '18 at 13:16

2 Answers2

1

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)

Stephan
  • 53,940
  • 10
  • 58
  • 91
  • In my fist test it's working well, thank you very much, Stephan! I don't understand the logic behind your code, because if the current line matches the string ("%%#==%string%") I suppose %%# = kkklllmmm. If "line=%%#", in my mind logically we have line = kkklllmmm. How did you get the previous line? – Daniel Sian Jun 05 '18 at 21:20
  • Is it possible to improve the code to make the filtering more comprehensive? I mean, how about if I need to find more than one string, maybe 3 or 4 different strings, and, for every string, a related .zip is output in a master output_list. Thanks – Daniel Sian Jun 05 '18 at 21:45
  • Hey @Stephan, you are master. Thanks for your time! As you can see I'm learning and I'll try to implement the code you provided in your Edit answer. The first option (1 string) is working like a charm. I'm still unable to up-vote your answer because of my low reputation :-/ – Daniel Sian Jun 07 '18 at 03:00
0

You use a PowerShell command:

powershell -nop -c "sls List.txt -Patt 'kkklllmmm' -Co 1,0|%{$_.Context.PreContext}">output.txt

Or wrap it into a batch:

@echo off
setlocal enabledelayedexpansion
set "input_list=list.txt"
set "string=kkklllmmm"
set "output_list=output.txt"
(powershell -nop -c "sls '%input_List%' -Patt '%string%' -Co 1,0|%%{$_.Context.PreContext}"
)>"%output_list%"

Sample output

orange.zip
pineaple.zip
  • It works fine! I have zero experience with powershell, so I'm unable to parse your code to understand what you have done. And because this filtering task will be used in a major code, I prefer a pure batch so I have more control about what is happening. Thank you very much for your time! – Daniel Sian Jun 05 '18 at 21:38