正如 dbenham 所说,它也可以用 for/f 完成,但它有点复杂。
简单的 80% 解决方案是
setlocal EnableDelayedExpansion
set "var="
set LF=^
rem *** Two empty lines are required for the linefeed
FOR /F "delims=" %%a in (myFile.txt) do (
set "var=!var!!LF!%%a"
)
echo !var!
但它失败了:
- 如果一行是空白的,它将被跳过
- 如果一行以;EOL 字符开头
- 如果一行包含!(和插入符号)
但是你可以使用更复杂的解决方案
@echo off
SETLOCAL DisableDelayedExpansion
set "all="
FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ aux1.txt"`) do (
set "line=%%a"
SETLOCAL EnableDelayedExpansion
set "line=!line:#=#S!"
set "line=!line:*:=!"
for /F "delims=" %%p in ("!all!#L!line!") do (
ENDLOCAL
set "all=%%p"
)
)
SETLOCAL EnableDelayedExpansion
if defined all (
set "all=!all:~2!"
set ^"all=!all:#L=^
!"
set "all=!all:#S=#!"
)
echo !all!
代码做什么?
首先,findstr /n ^^将在每一行前面加上一个行号和一个冒号,比如
1:My first Line
2:; beginning with a semicolon
3:
4:there was an empty line
这解决了空行的问题,并且标准的 EOL 字符;可以被忽略。
要获取该行的内容,将值设置为一个变量,同时禁用延迟扩展,这解决了!和^字符的问题。
去掉行号和冒号,会启用延迟扩展(不,delim:解决不了)。
然后全部#替换为#S,这将首先完成,因为删除该行的前缀可能为空并且替换将失败。
但是我为什么要换?
那是因为我不能在这里插入换行符,因为下面的 FOR/F 会因嵌入换行符而失败,
所以我只添加换行符标记(在这种情况下我使用#L),但文件的内容也可以包含 a #L,但是通过#用#S所有标记 替换所有是唯一的。
在标记之后,使用 关闭/禁用延迟扩展存在问题endlocal,但保留修改后的all和line变量的内容。
这是通过FOR/F-endlocal技巧完成的,因为可以在屏障 %%p后面传输内容。endlocal
然后在阅读完整文件后,我检查是否all已定义,因为对于空文件,它将为空。
然后第一个换行标记 #L将被删除,所有其他标记都将替换为真正的换行字符。
然后将锐利的安全#S器恢复为#.
就是这样,所以即使这个解决方案显然......