简体   繁体   English

Windows Batch:如何使用循环为 /f 保留空行

[英]Windows Batch: How to keep empty lines with loop for /f

I'm searching how to keep empty lines when I browse a file with a for loop.当我使用 for 循环浏览文件时,我正在搜索如何保留空行。

for /f "tokens=1* delims=[" %%i in ('type "test1.txt" ^| find /v /n ""') do (
SET tmp=%%i
echo !tmp! >> test2.txt
)

Actually it works for everybody, but as far as I'm concerned it does not work.实际上它对每个人都有效,但就我而言它不起作用。 For instance if test1.txt content is:例如如果 test1.txt 内容是:

Hello I come from France
I live in Paris

I'm sorry I don't know English, could we speak French please?
If it doesn't bother you

Thank you

Result in test2.txt will be: test2.txt 中的结果将是:

[1 
[2 
[3 
[4 
[5 
[6 
[7 

If I put off the "1" near the star "*", result is:如果我在星“*”附近推迟“1”,结果是:

[1]Hello I come from France 
[2]I live in Paris 
[3] 
[4]I'm sorry I don't know English, could we speak French please? 
[5]If it doesn't bother you 
[6] 
[7]Thank you 

Desired output is:期望的输出是:

Hello I come from France
I live in Paris

I'm sorry I don't know English, could we speak French please?
If it doesn't bother you

Thank you

Can you please help me to solve this trouble?你能帮我解决这个麻烦吗?

This could be done as这可以做为

@echo off
    setlocal enableextensions disabledelayedexpansion

    for /f "tokens=1,* delims=]" %%a in ('
        find /n /v "" ^< "file1.txt"
    ') do (
        >> "file2.txt" echo(%%b
    )

The output from the inner find command is like内部find命令的输出类似于

[123]texttexttext

The code uses the closing bracket as delimiter, so the tokens (we are requesting two tokens: 1,* or 1* ) are代码使用右括号作为分隔符,因此令牌(我们请求两个令牌: 1,*1* )是

[123 texttexttext
^    ^
1    2
%%a  %%b

But, as repeated delimiters are handled as only one delimiter, if one line begins with a closing bracket it will be removed.但是,由于重复的分隔符仅作为一个分隔符处理,如果一行以右括号开头,它将被删除。 This can be prevented as这可以防止,因为

@echo off
    setlocal enableextensions disabledelayedexpansion

    for /f "tokens=1,* delims=0123456789" %%a in ('
        find /n /v "" ^< "file1.txt"
    ') do (
        set "line=%%b"
        setlocal enabledelayedexpansion
        >>"file2.txt" echo(!line:~1!
        endlocal
    )

Here the numbers are used as delimiters and the line is tokenized as这里的数字用作分隔符,该行被标记为

[   ]texttexttext
^   ^
%%a %%b

Then the value of the second token is stored inside a variable, with delayed expansion disabled to avoid problems with exclamations inside the data (that will be handled/replaced by the parser if delayed expansion is active)然后将第二个标记的值存储在一个变量中,禁用延迟扩展以避免数据中的感叹号出现问题(如果延迟扩展处于活动状态,解析器将处理/替换)

Once the data is inside the variable, delayed expansion is activated (something needed as we want to retrieve the contents from a variable changed inside a block of code) to output the line from the second position (first character in string is 0) to remove the closing bracket.一旦数据在变量内部,延迟扩展就会被激活(因为我们想要从代码块内更改的变量中检索内容,所以需要这样做)以从第二个位置(字符串中的第一个字符为 0)输出行以删除右括号。 Once done, delayed expansion is disabled again.完成后,延迟扩展将再次禁用。

edited as the OP has to incorporate it to a larger/complex script, this code should face the most usual problems编辑成的OP具有将它合并到更大的/复杂的脚本,此代码应面临的最常见的问题

@echo off
    rem For this test we will have delayed expansion from the start
    setlocal enableextensions enabledelayedexpansion

    rem External code block that will make delayed expansion necessary
    if 1==1 ( 
        rem Variables changed inside block
        set "input_file=file1.txt"
        set "output_file=file2.txt"

        rem Grab a reference to the content of the file variables
        for %%i in ("!input_file!") do for %%o in ("!output_file!") do (

            rem Prepare the environment for file work
            setlocal disabledelayedexpansion

            rem Prepare output file
            type nul > "%%~fo"

            rem Process input file and write to output file
            for /f "tokens=1,* delims=0123456789" %%a in ('
                find /n /v "" ^< "%%~fi"
            ') do (
                set "line=%%b"
                setlocal enabledelayedexpansion
                >>"%%~fo" echo(!line:~1!
                endlocal
            )

            rem Restore the previous environment
            endlocal
        )
    )

Here is a slightly different variant using the findstr command rather than find and doing the redirection to the output file file2.txt only once rather than per for /F loop iteration:这是一个稍微不同的变体,使用findstr命令而不是find并且只 重定向到输出文件file2.txt一次,而不是 per for /F循环迭代:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
>> "file2.txt" (
    for /F "delims=" %%a in ('findstr /N "^" "file1.txt"') do (
        set "line=%%a"
        setlocal EnableDelayedExpansion
        echo(!line:*:=!
        endlocal
    )
)
endlocal

The findstr command precedes every line by a line number and a colon, like this: findstr命令在每一行前面加上一个行号和一个冒号,像这样:

 1:Hello I come from France

The sub-string substitution portion !line:*:=! 子字符串替换部分!line:*:=! replaces everything up to the first colon (due to * ) by nothing, thus removing this.不替换第一个冒号(由于* )之前的所有内容,从而删除它。

Replace the >> operator by > in case you want to overwrite an already existing file rather than to append to it.如果您想覆盖已经存在的文件而不是附加到它,请将>>运算符替换为>

Send your loop command to con: device:将您的循环命令发送到con: device:

  • In command line:在命令行中:

for /F tokens^=^* %F in ('type File.txt ^>con:')do @echo/%F

  • In your bat file:在你的 bat 文件中:
for /F tokens^=^* %%F in ('type File.txt ^>con:')do echo;%%F

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM