如何在将输出重定向到文件的同时"foo 1"使用echo命令回显字符串,以便将整个字符串写入文件?
C:\>echo foo 1>foo.txt
C:\>type foo.txt
foo
C:\>xxd -g1 a.txt
0000000: 66 6f 6f 20 0d 0a foo ..
Run Code Online (Sandbox Code Playgroud)
上面的实验表明只有"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
Run Code Online (Sandbox Code Playgroud)
当我执行此脚本时,它的行为符合要求,即在log.txt中写入三行日志.
C:\>foo
C:\>type log.txt
start script
foo
end script
Run Code Online (Sandbox Code Playgroud)
现在考虑以下脚本,其中第二行日志已被修改"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
Run Code Online (Sandbox Code Playgroud)
这引起了一些惊喜.正如您在下面的输出中看到的,我们看到的"foo"不是"foo 1"日志文件.
C:\Users\pals3\Desktop>foo
C:\Users\pals3\Desktop>type log.txt
start script
foo
end script
Run Code Online (Sandbox Code Playgroud)
通过删除@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
Run Code Online (Sandbox Code Playgroud)
从这里可以看出,只要>>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
Run Code Online (Sandbox Code Playgroud)
但是,这意味着每行日志都会以空格字符为后缀,从迂腐的角度来看这是不理想的,当有人想用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
Run Code Online (Sandbox Code Playgroud)
有没有办法以一种方式编写:log子程序,它可以摆脱我上面提到的惊喜,而不是在每行日志末尾写一个额外的空格?
试试括号:
@echo off
call :log "start script"
call :log "foo 1"
call :log "end script"
goto :eof
:log
(echo %~1)>>log.txt
goto :eof
Run Code Online (Sandbox Code Playgroud)
一个鲜为人知的事实是,您可以在命令之前指定重定向:
@echo off
call :log "start script"
call :log "foo 1"
call :log "end script"
goto :eof
:log
>>log.txt echo %~1
goto :eof
Run Code Online (Sandbox Code Playgroud)
产生:
start script
foo 1
end script
Run Code Online (Sandbox Code Playgroud)