开发者

Nesting for loop in batch file

I want to nest a for loop inside a batch file to delete carriage return. I tried it like you can see below but it does not work.

@echo off
setLocal EnableDelayedExpansion

for /f "tokens=* delims= " %%a in (Listfil开发者_高级运维e.txt) do (
    set /a N+=1
    set v!N!=%%a
)

for /l %%i in (1, 1, %N%) do (
    echo !v%%i!
    for /r "tokens=* delims=" %%i in (windows.cpp) do (
        echo %%i >> Linux11.cpp
    )
)
pause

Here I want to check with windows.cpp. If its working I like to change windows .cpp with !v%%i!


You cannot do this in a batch file. You have no way of addressing or writing arbitrary characters. Every tool on Windows normally makes sure to output Windows line breaks (i.e. CR+LF). Some can read Unix-style line breaks just fine, which is why you can easily convert from them. But to them isn't possible.

Also as a word of caution: Source code files often contain blank lines (at least mine do) that are for readability. for /f skips empty lines which is why you're mangling the files for your human readers there. Please don't do that.

As for your question: When nesting two loops you have to make sure that they don't use the same loop variable. Show me a language where code like you wrote actually works.

Something like

for /l %%i in (1, 1, %N%) do ( 
  echo !v%%i! 
  for /f "tokens=* delims=" %%l in ("!v%%i!") do (   
    rem do whatever you want to do with the lines
  )
)

should probably work better (you missed the final closing parenthesis as well). Thing to remember: If you want to use a certain variable instead of a fixed file name it surely helps replacing that fixed file name by that variable.


It would be probably easiest to use some unix2dos/dos2unix converter to do that or some win32 flavor of sed.


The intrinsic issue of your code is already addressed by another answer, hence I am going to focus on the main task you are trying to accomplish, namely converting DOS/Windows-style end-of-line markers (or line-breaks) to Unix-style ones.

Doing this is very tricky in a batch file, but give the following script a try. Supposing it is called convert.bat, and the original text file is named convert.txt, run the script using the following command line:

convert.bat "convert.txt" LF

The name of the returned file will get the original file name with _converted_EOL appended. The second argument LF specifies Unix-style line-breaks; omitting it will return DOS/Windows-style ones.

So here is the code:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem check whether or not an existing file is given as the first argument
>&2 (
    if "%~1"=="" (
        echo No file specified.
        exit /B 2
    ) else if not exist "%~1" (
        echo File "%~1" not found.
        exit /B 1
    )
)

rem get carriage-return character
for /F %%A in ('copy /Z "%~0" nul') do set "CR=%%A"

rem get line-feed character (the two empty lines afterwards are mandatory!)
(set ^"LF=^
%= blank line =%
^")

rem check which line-break is given by the second argument
rem (`CR` - carriage return (Mac); `LF` - line feed (Unix);
rem  anything else or nothing - CR+LF (Windows, default))
setlocal EnableDelayedexpansion
set "BR=!CR!!LF!"
if /I "%~2"=="CR" set "BR=!CR!" & (>&2 echo CR not supported.) & exit /B 3
if /I "%~2"=="LF" set "BR=!LF!"

rem convert line-breaks; append `_converted_EOL` to file name
setlocal DisableDelayedExpansion
> "%~n1_converted_EOL%~x1" (
    for /F delims^=^ eol^= %%L in ('
        findstr /N /R "^" "%~1"
    ') do (
        set "LINE=%%L"
        rem firstly, precede every line with a dummy character (`:`) and
        rem append the specified line-break in order to avoid the loss of
        rem leading white-spaces or trouble with leading equal-to signs,
        rem all caused by `set /P`, which is needed here to return the
        rem line without a trailing DOS/Windows-style line-break (opposed
        rem to `echo`); then, let `pause` strip off that character;
        rem lastly, let `findstr` return the remainder;
        rem (the `rem` suffix is just there to fix syntax highlighting)
        cmd /V /C ^< nul set /P #="!LINE:*:=:!!BR!" | (> nul pause & findstr "^") & rem/ "^"
    )
)
endlocal
endlocal

endlocal
exit /B

The following restrictions apply:

  • no line must be longer than about 8190 characters (this is a general limitation of batch files);
  • the file must not contain any null-bytes (well, a normal text file should not hold such, but Unicode-encoded do);
  • the last line of the returned file will always be terminated by a line-break, even if the respective original line is not;

And here is another solution for line-break conversions: Convert all CR to CRLF in text file using CMD

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜