1

The following loop/function is supposed to edit a file (just replacing the second line in the file). The original file contains one > 165000 signs long line and just this line is simply disappearing in the new file after performing this loop.

setlocal EnableDelayedExpansion
set /a count=0
>"%~3" (
  for /f "usebackq delims=" %%A in ("%~2") do  (
    if !count!==1 (echo ^<html^>) else (
      setlocal DisableDelayedExpansion
      echo.%%A
      endlocal)
    set /a count+=1
  )
)
endlocal
goto:eof

I assume that it has to do with the maximum length a variable (%%A) can store.. is there a way to avoid this behavior?

Thanks in advance!

jww
  • 97,681
  • 90
  • 411
  • 885
DragonGamer
  • 834
  • 3
  • 9
  • 27

2 Answers2

2

Native batch cannot work with lines longer than ~8191 bytes unless you resort to extreme measures that read one byte at a time (it involves creating a dummy file with length >= source, and using FC to derive the bytes). This is one of many reasons why I rarely use batch to modify files.

I would use my JREPL.BAT utility:

call jrepl "^.*" "<html>" /jbegln "skip=(ln!=2)" /f "%~2" /o "%~3" 

But there are many other options.

You could write custom code using JScript or VBS, executed via CSCRIPT. Or you could use PowerShell.

Or you could get a Windows port of sed, or awk, or ...


Update - Possible pure batch solution

The following may work if all of the following are true:

  • You don't care if tabs are converted into a string of spaces
  • The first line length is <= 1021 bytes, and it does not have trailing control characters
  • The total number of lines is <64k
  • (there may be another limitation that I cannot remember)
@echo off
setlocal enableDelayedExpansion
>"%~3" (
  set "ln="
  <"%~2" set /p "ln="
  echo(!ln!
  echo ^<html^>
  more +2 "%~2"
)
dbenham
  • 127,446
  • 28
  • 251
  • 390
  • Thank you! That jrepl.bat is amazing! o: Just one question though (since I'm quite a beginner with batch), who would I go about replacing the following string? It contains apostrophes and I've found no method of escaping them... – DragonGamer Feb 09 '15 at 00:51
  • @DragonGamer - I think you mean it contains double quotes, not apostrophes. You can use `\xnn` to get any byte code, where `nn` is the hex notation. You must add the `/X` option to use it in the replace string. The code for a double quote is `\x22`. Alternatively, you could use `\q`, which always requires the `/X` option. Read the documentation for a full description of the `/X` option. – dbenham Feb 09 '15 at 01:12
1

If the first and second lines in the file are less than 1 KB size, then the pure Batch file below should solve your problem:

@echo off
setlocal EnableDelayedExpansion

< "%~2" (

   rem Read the first line from redirected Stdin and copy it to Stdout
   set /P "line="
   echo !line!

   rem Read the second line and replace it by another one
   set /P "line="
   echo ^<html^>

   rem Copy the rest of lines to Stdout
   findstr "^"

) > "%~3"

For further description of this method, see this post; you may also see another example at this one.

Community
  • 1
  • 1
Aacini
  • 65,180
  • 12
  • 72
  • 108
  • Interesting method, but sadly it says: FINDSTR: Line 244 is too long :( – DragonGamer Feb 09 '15 at 00:49
  • Yes, FINDSTR has an 8191 byte line length limit when using redirected or piped input. There is no line length limit when passing the name of the file (FINDSTR opens the file), but that doesn't help in this case. Refer to [What are the undocumented features and limitations of the Windows FINDSTR command?](http://stackoverflow.com/q/8844868/1012053) for more info. – dbenham Feb 09 '15 at 01:38