4

The following code works pretty well printing the paragraph

@echo off
setlocal disableDelayedExpansion
set "skip="
for /f "delims=:" %%N in (
  'findstr /x /n ":::BeginText" "%~f0"'
) do if not defined skip set skip=%%N
>test.txt (
  for /f "skip=%skip% tokens=*" %%A in (
   'findstr /n "^" "%~f0"'
  ) do (
    set "line=%%A"
    setlocal enableDelayedExpansion
    echo(!line:*:=!
    endlocal
  )
)
type test.txt
exit /b

:::BeginText
This text will be exactly preserved with the following limitations:

  1) Each line will be terminated by CR LF even if original has only LF.

  2) Lines are limited in length to approximately 8191 bytes.

Special characters like ^ & < > | etc. do not cause a problem.
Empty lines are preserved!
;Lines beginning with ; are preserved.
:::Leading : are preserved

Is there a way to add a text marker like :::Endtext so that only the paragraph between :::BeginText and :::Endtext is printed.

munish
  • 4,505
  • 14
  • 53
  • 83
  • What is the purpose of the opening paren in this line: `echo(!line:*:=!`? – utapyngo Feb 10 '13 at 11:15
  • @utapyngo: `!line:*:=!` follows this syntax: `!varname:substr1=substr2!`, whereby every occurrence of `substr1` in `varname` is replaced with `substr2`. In your particular example, `substr1` contains a mask (`*` stands for any number of any chars) and `substr2` is empty, meaning the matched substring will simply be deleted. – Andriy M Feb 10 '13 at 16:46
  • @AndriyM: I know. I was asking about the left bracket just after `echo`. I tried to remove it but without it it does not work. – utapyngo Feb 10 '13 at 16:56
  • @utapyngo: Ah yes, sorry, you said that explicitly and it was silly of me to overlook it. This is to prevent e.g. an `ECHO is OFF` message when the expression evaluates to an empty string. As to why `(` and not something else, please see [this answer](http://stackoverflow.com/a/6526957/297408 "Escaping a batch file echo that starts with a forward slash and question mark"). – Andriy M Feb 10 '13 at 19:02

1 Answers1

8

Sure :-)

And you can embed multiple named paragraphs within your script and selectively write them by using a unique label for each.

The named text can appear anywhere within the script as long as GOTO and/or EXIT /B prevent the text from being executed.

The script below encapsulates the logic in a :printParagraph routine for convenience.

@echo off
setlocal disableDelayedExpansion
goto :start

:::BeginText1
Paragraph 1
  is preserved

Bye!
:::EndText

:start
echo Print paragraph 1 directly to screen
echo ------------------------------------------
call :printParagraph 1
echo ------------------------------------------
echo(
echo(

call :printParagraph 2 >test.txt
echo Write paragraph 2 to a file and type file
echo ------------------------------------------
type test.txt
echo ------------------------------------------
echo(
echo(

echo Print paragraph 3 directly to screen
echo ------------------------------------------
call :printParagraph 3
echo ------------------------------------------
echo(
echo(

exit /b

:::BeginText2
This is paragraph 2

Pure poetry
:::EndText

:printParagraph
set "skip="
for /f "delims=:" %%N in (
  'findstr /x /n ":::BeginText%~1" "%~f0"'
) do if not defined skip set skip=%%N
set "end="
for /f "delims=:" %%N in (
  'findstr /x /n ":::EndText" "%~f0"'
) do if %%N gtr %skip% if not defined end set end=%%N
for /f "skip=%skip% tokens=*" %%A in (
 'findstr /n "^" "%~f0"'
) do (
  for /f "delims=:" %%N in ("%%A") do if %%N geq %end% exit /b
  set "line=%%A"
  setlocal enableDelayedExpansion
  echo(!line:*:=!
  endlocal
)
exit /b

:::BeginText3
One more...

  ...for good measure
:::EndText
dbenham
  • 127,446
  • 28
  • 251
  • 390