3

I've successfully written a script which takes a string to search for in a specific file, and then outputs the line where it first occurs, and then I take that value into a for-loop and skips parsing that number of lines and write its contents to a new file. However I do not get blank lines which I find quite problematic to solve.

The string I'm searching for is "/]", caches the line number where it occurs, then accumulates it into a variable with comma-seperation. I then take that variable into a for-loop again and retrieve the first occurring value as my final "skip this number of lines"-variable, which I then use at the bottom for-loop which reads that file again and writes its values to a new files and skips that number of lines at the beginning of the file.

So heres the part of the script that does what I'm describing above:

setlocal enabledelayedexpansion
setlocal enableextensions
set live_svn_access_file=c:\csvn\data\conf\svn_access_file
set of=c:\test.txt

for /f "Tokens=1 Delims=:" %%i in ('findstr /n /c:"/]" %live_svn_access_file%') do (
    rem cache value in a variable
    set line=%%i
    rem accumulate data to one variable
    if defined line set skip=!skip!, !line!
)
rem strip first two characters in variable ", "
set skip=!skip:~2!
rem strip everything except first value in array
for /f "Tokens=1 Delims=," %%i in ('echo !skip!') do (
    rem store value in a variable
    set skip=%%i
)
rem calculate lines - 1 (arithmetic)
set /a skip=!skip!-1
set skip=!skip!

if not defined skip set error=Could not automatically find which parts to skip from live svn_access_file && goto error-handler

for /f "Tokens=* Delims= Skip=%skip%" %%i in (%live_svn_access_file%) do (
    rem cache value in a variable
    set read-input=%%i
    rem write and append content of variable to output-file
    echo !read-input! >> %of%
)

I've rewritten the script to match the working one, this is the changed script:

setlocal enabledelayedexpansion
setlocal enableextensions
set live_svn_access_file=c:\csvn\data\conf\svn_access_file
set of=c:\test.txt

for /f "Tokens=1 Delims=:" %%i in ('findstr /n /r /c:"\[..*\]" %live_svn_access_file%') do (
    rem cache value in a variable
    set line=%%i
    rem accumulate data to one variable
    if defined line set skip=!skip!, !line!
)
rem take the 2nd sections linenumber into a variable, skipping the first [*foo*]
for /f "Tokens=2 Delims=," %%i in ('"echo !skip!"') do (
    rem store value in a variable
    set skip=%%i
)
rem add 1 line to skip from retrieved value
set /a skip=!skip!-1

rem verify that number of lines to skip has been successfully retrieved, if not go to error-handler
if not defined skip set error=Could not automatically find which parts to skip from live svn_access_file && goto error-handler
if ["%skip%"] LSS ["1"] set error=Number of lines to skip was less than 1, this will most likely fail && goto error-handler

rem read live svn_access_file, but skip X-lines and write to output-file
setlocal DisableDelayedExpansion
for /f "usebackq Delims= Skip=%skip%" %%i in (`"findstr /n ^^ %live_svn_access_file%"`) do (
    rem cache value in a variable
    set read-input=%%i
    rem write and append content of variable to output-file
    setlocal EnableDelayedExpansion
    rem strip line number prefix
    set read-input=!read-input:*:=!
    rem write read lines to output-file
    echo(!read-input!>>%of%
    endlocal
)
  • The line `if not defined read-input echo. >> %of%` produces a line with one space instead of an empty line, you could change to `(>> %of% echo.)`. You should avoid `echo.` it's slow and it can fail, it's better to use `echo(`. The `skip=%skip%` option will fail, if `%skip%` is zero – jeb Oct 26 '11 at 13:22
  • I've changed the script to match your suggestions, please verify that I understood you correctly. – Niklas J. MacDowall Oct 26 '11 at 14:22
  • IMHO your code should work stable now – jeb Oct 28 '11 at 09:01
  • @Niklas Are you seeing any removal of exclamation points from your original file? I have a variant of this and am still seeing that problem. – Jared Oct 28 '11 at 19:51
  • @Jared I haven't tested with exclamation marks, as they will not occur anyway in my file. – Niklas J. MacDowall Oct 31 '11 at 06:57

1 Answers1

3

You got two main problems, a FOR /F can't read empty lines (as you discover) and if you use delayed expansion you got trouble with exclamation marks and carets in the line set read-input=%%i.

You can solve both, the empty lines with prefixing each line with a line number by using findstr. The second with the delayed toggling technic.

SETLOCAL DisableDelayedExpansion
FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ t.txt"`) do (
    set "var=%%a"
    SETLOCAL EnableDelayedExpansion
    set "var=!var:*:=!" This removes the prefix
    echo(!var!
    ENDLOCAL
)
jeb
  • 78,592
  • 17
  • 171
  • 225
  • Thank you, but I can't use a command (findstr) inside the for-loop, it must be a file due to the reason I'm using the "Skip"-option to skip some lines. – Niklas J. MacDowall Oct 25 '11 at 11:10
  • You can also use the skip-option with this construct – jeb Oct 25 '11 at 12:29
  • I will try that. Thanks. Btw, is echo(!var! closed correctly? – Niklas J. MacDowall Oct 26 '11 at 08:26
  • Yes "echo(" is the best way to echo even an empty line without problems and avoid the output of "ECHO is On" – jeb Oct 26 '11 at 08:39
  • @jeb: Excuse me. To show an empty line with `echo` command any _unused_ special char may be used. I strongly suggest not use any character that is already used for other purposes, like `.()` etc. I suggest to use the dash that is already used in many commands to indicate command options: `echo/`. :) – Aacini Nov 01 '11 at 23:48
  • The `echo(!var!` have to handle empty lines, but also `/?` or `on` and other content in `!var!`. Your `echo/` version fails with a single `?` – jeb Nov 02 '11 at 04:49
  • 1
    @jeb: Yes, you are right! I never tought about this case... However, I still think that `(` is not adequate because it interfere with the review of a program with parentheses. Perhaps we could use the standard delimiters `,;=` or `:\` (I like `echo\`), what do you think? I apologize for all this matter, but I think is important we agree in a standard about this point ;-) – Aacini Nov 02 '11 at 06:35
  • @jeb: Excuse me, an error happened in my web access when I was editing my previous comment... I suggest to use the back-slash: `echo\\` – Aacini Nov 02 '11 at 06:48
  • 'Echo\' also fails, but perhaps you better open a new question – jeb Nov 02 '11 at 07:44
  • I found an old answer to this topic [SO:Escaping a batch file echo that starts with `/?`](http://stackoverflow.com/questions/6514746/escaping-a-batch-file-echo-that-starts-with-a-forward-slash-and-question-mark/6526957#6526957) – jeb Nov 03 '11 at 09:20