如何使用Windows批处理脚本将以“1”结尾的行写入文件?

5

简短问题

如何使用echo命令将字符串"foo 1"输出到文件,以便整个字符串都被写入文件?

C:\>echo foo 1>foo.txt

C:\>type foo.txt
foo

C:\>xxd -g1 a.txt
0000000: 66 6f 6f 20 0d 0a                                foo ..

上面的实验表明,只有"foo "被写入文件,因为命令中的"1"被解释为重定向运算符1>的一部分。请注意,echo foo 1 > foo.txt不是一个解决方案,因为它会在字符串末尾写入一个不必要的空格,将"foo 1 "写入文件。
长问题:
考虑以下Windows批处理脚本。
@echo off
call :log "start script"
call :log "foo"
call :log "end script"
goto :eof

:log
echo %~1>>log.txt
goto :eof

当我执行这个脚本时,它表现得和期望的一样,即在log.txt中写入了三行日志。
C:\>foo

C:\>type log.txt
start script
foo
end script

现在考虑以下脚本,其中日志的第二行已经从"foo"修改为"foo 1"
@echo off
call :log "start script"
call :log "foo 1"
call :log "end script"
goto :eof

:log
echo %~1>>log.txt
goto :eof

这有点让人惊讶。如下输出所示,我们在日志文件中看到的是"foo"而不是"foo 1"

C:\Users\pals3\Desktop>foo

C:\Users\pals3\Desktop>type log.txt
start script
foo
end script

从脚本中删除包含@echo off的第一行,然后执行脚本即可理解其发生原因。
C:\>foo.cmd

C:\>call :log "start script"

C:\>echo start script 1>>log.txt

C:\>goto :eof

C:\>call :log "foo 1"

C:\>echo foo  1>>log.txt

C:\>goto :eof

C:\>call :log "end script"

C:\>echo end script 1>>log.txt

C:\>goto :eof

C:\>goto :eof

在这里可以看到,无论何时脚本中出现>>log.txt,命令解释器都会用同义的语法1>>log.txt来替换它。这意味着我们记录"foo 1"的命令现在被执行为echo foo 1>>log.txt,它只是将"foo"写入日志文件。
一个简单的解决方案是,在脚本中将语句echo %~1>>log.txt替换为echo %~1 >>log.txt
@echo off
call :log "start script"
call :log "foo 1"
call :log "end script"
goto :eof

:log
echo %~1 >>log.txt
goto :eof

然而,这意味着每行日志都会以一个空格字符作为后缀,从严谨的角度来看并不理想,并且当需要使用grep过滤日志文件时,可能会有一点混淆。

C:\>foo

C:\>type log.txt
start script
foo 1
end script

C:\>xxd -g1 log.txt
0000000: 73 74 61 72 74 20 73 63 72 69 70 74 20 0d 0a 66  start script ..f
0000010: 6f 6f 20 31 20 0d 0a 65 6e 64 20 73 63 72 69 70  oo 1 ..end scrip
0000020: 74 20 0d 0a

有没有一种方法可以编写:log子程序,以消除上述惊喜,同时又不在每行日志的末尾写入额外的空格?
3个回答

5
尝试使用括号:
@echo off
call :log "start script"
call :log "foo 1"
call :log "end script"
goto :eof

:log
(echo %~1)>>log.txt
goto :eof

这对大多数情况都有效,但这不是一个通用解决方案。当您运行:call :log "(foo)"时,它会失败。 - Susam Pal

3

很少有人知道,在命令之前可以指定重定向:

@echo off
call :log "start script"
call :log "foo 1"
call :log "end script"
goto :eof

:log
>>log.txt echo %~1
goto :eof

生成:

start script
foo 1
end script

1
同样,这可以被使用。任何)字符需要转义,但在不需要转义的情况下,它会导致一个整洁的块。
(
echo 123
echo %~1
echo 321
)>log.txt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接