windows 在批处理文件中嵌套 for 循环

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3137997/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 14:43:51  来源:igfitidea点击:

Nesting for loop in batch file

windowsfor-loopbatch-filecmd

提问by user375191

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.

我想在批处理文件中嵌套一个 for 循环来删除回车。我试过了,就像你在下面看到的那样,但它不起作用。

@echo off
setLocal EnableDelayedExpansion

for /f "tokens=* delims= " %%a in (Listfile.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!

在这里,我想检查 windows.cpp。如果它可以工作,我喜欢用 !v%%i! 更改 windows .cpp!

回答by Joey

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 readUnix-style line breaks just fine, which is why you can easily convert fromthem. But tothem isn't possible.

您不能在批处理文件中执行此操作。您无法寻址或写入任意字符。Windows 上的每个工具通常都会确保输出 Windows 换行符(即 CR+LF)。有些人可以很好地读取Unix 样式的换行符,这就是为什么您可以轻松地它们转换。但他们来说是不可能的。

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

还要提醒一句:源代码文件通常包含空白行(至少我是这样做的),以提高可读性。for /f跳过空行,这就是您在那里为人类读者修改文件的原因。请不要那样做。

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.

应该会更好(你也错过了最后的右括号)。要记住的事情:如果您想使用某个变量而不是固定文件名,它肯定有助于用该变量替换该固定文件名。

回答by Joey

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

使用一些unix2dos/dos2unix转换器或一些 win32 风格的 sed可能是最简单的。

回答by aschipfl

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.

您的代码的内在问题已经由另一个答案解决,因此我将专注于您要完成的主要任务,即将 DOS/Windows 样式的行尾标记(或换行符)转换为 Unix -风格的。

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,请使用以下命令行运行脚本:

convert.bat "convert.txt" LF

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

返回的文件名将_converted_EOL附加原始文件名。第二个参数LF指定 Unix 风格的换行符;省略它将返回 DOS/Windows 风格的。

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;
  • 任何行的长度不得超过 8190 个字符(这是批处理文件的一般限制);
  • 该文件不能包含任何空字节(好吧,普通的文本文件不应该包含这样的内容,但是 Unicode 编码的可以);
  • 返回文件的最后一行将始终以换行符终止,即使相应的原始行不是;


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

这是换行转换的另一种解决方案:Convert all CR to CRLF in text file using CMD