7

我正在搜索如何在使用 for 循环浏览文件时保留空行。

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

实际上它适用于所有人,但就我而言,它不起作用。例如,如果 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

test2.txt 中的结果将是:

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

如果我把星号“*”附近的“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 

期望的输出是:

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

你能帮我解决这个问题吗?

4

3 回答 3

7

这可以作为

@echo off
    setlocal enableextensions disabledelayedexpansion

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

内部find命令的输出就像

[123]texttexttext

该代码使用右括号作为分隔符,因此标​​记(我们请求两个标记:1,*1*)是

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

但是,由于重复的定界符仅作为一个定界符处理,如果一行以右括号开头,它将被删除。这可以防止为

@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
    )

在这里,数字用作分隔符,并且该行被标记为

[   ]texttexttext
^   ^
%%a %%b

然后将第二个标记的值存储在变量中,禁用延迟扩展以避免数据内部出现感叹号问题(如果延迟扩展处于活动状态,则将由解析器处理/替换)

一旦数据在变量中,延迟扩展被激活(需要一些东西,因为我们想要从代码块内更改的变量中检索内容)以从第二个位置输出行(字符串中的第一个字符为 0)以删除右括号。完成后,延迟扩展将再次禁用。

由于 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
        )
    )
于 2015-07-09T10:35:27.233 回答
2

这是一个稍微不同的变体,它使用findstr命令而不是find重定向到输出文件file2.txt一次而不是每次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

findstr命令在每一行前面加上一个行号和一个冒号,如下所示:

1:Hello I come from France

子字符串替换部分!line:*:=!将第一个冒号(由于 )之前的所有内容都替换为任何*内容,从而将其删除。

如果您想要覆盖已经存在的文件而不是附加到它,请替换>>运算符。>

于 2019-04-24T12:21:51.713 回答
1

将循环命令发送到con:设备:

  • 在命令行中:

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

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

于 2020-01-31T19:38:53.630 回答