如何在Windows批处理文件中实现Linux shell命令echo -n
的效果,这个命令可以去掉输出内容末尾的换行符号?
目的是为了在循环中将内容写入同一行。
如何在Windows批处理文件中实现Linux shell命令echo -n
的效果,这个命令可以去掉输出内容末尾的换行符号?
目的是为了在循环中将内容写入同一行。
使用set
和/p
参数,您可以在不换行的情况下输出:
C:\> echo Hello World
Hello World
C:\> echo|set /p="Hello World"
Hello World
C:\>
<nul set /p =Hello
。 set /p
无法输出等号作为第一个字符,也无法输出空格/制表符。 - jeb< nul
是从 NUL
设备进行的重定向。它不包含任何内容,但对于 set /p
来说已经足够停止等待用户输入了。 - jeb使用echo | set /p=
或者<NUL set /p=
都可以用来阻止换行。
然而,当编写更高级的脚本并且检查ERRORLEVEL变得重要时,未指定变量名设置set /p=
将会使程序变得十分危险,因为这会将ERRORLEVEL设置为1。
一个更好的方法是只需像下面这样使用虚拟变量名:
echo | set /p dummyName=Hello World
这将完全产生您想要的结果,没有任何背景上的诡异事情发生,正如我不得不通过艰难的方式找出的那样,但这仅适用于管道版本;<NUL set /p dummyName=Hello
依旧会将ERRORLEVEL提高到1。
=
会导致语法错误。:writeInitialize
方法包含一个字符串文字,可能无法发布到该站点。备注说明了应该是什么字符序列。
< p > < code >:write 和 :writeVar
方法做了优化处理,只有包含前导问题字符的字符串才使用我的修改版 jeb 的 COPY 方法进行写入。非问题字符串会使用更简单且更快的 SET /P 方法进行写入。
@echo off
setlocal disableDelayedExpansion
call :writeInitialize
call :write "=hello"
call :write " world!%$write.sub%OK!"
echo(
setlocal enableDelayedExpansion
set lf=^
set "str= hello!lf!world^!!!$write.sub!hello!lf!world"
echo(
echo str=!str!
echo(
call :write "str="
call :writeVar str
echo(
exit /b
:write Str
::
:: Write the literal string Str to stdout without a terminating
:: carriage return or line feed. Enclosing quotes are stripped.
::
:: This routine works by calling :writeVar
::
setlocal disableDelayedExpansion
set "str=%~1"
call :writeVar str
exit /b
:writeVar StrVar
::
:: Writes the value of variable StrVar to stdout without a terminating
:: carriage return or line feed.
::
:: The routine relies on variables defined by :writeInitialize. If the
:: variables are not yet defined, then it calls :writeInitialize to
:: temporarily define them. Performance can be improved by explicitly
:: calling :writeInitialize once before the first call to :writeVar
::
if not defined %~1 exit /b
setlocal enableDelayedExpansion
if not defined $write.sub call :writeInitialize
set $write.special=1
if "!%~1:~0,1!" equ "^!" set "$write.special="
for /f delims^=^ eol^= %%A in ("!%~1:~0,1!") do (
if "%%A" neq "=" if "!$write.problemChars:%%A=!" equ "!$write.problemChars!" set "$write.special="
)
if not defined $write.special (
<nul set /p "=!%~1!"
exit /b
)
>"%$write.temp%_1.txt" (echo !str!!$write.sub!)
copy "%$write.temp%_1.txt" /a "%$write.temp%_2.txt" /b >nul
type "%$write.temp%_2.txt"
del "%$write.temp%_1.txt" "%$write.temp%_2.txt"
set "str2=!str:*%$write.sub%=%$write.sub%!"
if "!str2!" neq "!str!" <nul set /p "=!str2!"
exit /b
:writeInitialize
::
:: Defines 3 variables needed by the :write and :writeVar routines
::
:: $write.temp - specifies a base path for temporary files
::
:: $write.sub - contains the SUB character, also known as <CTRL-Z> or 0x1A
::
:: $write.problemChars - list of characters that cause problems for SET /P
:: <carriageReturn> <formFeed> <space> <tab> <0xFF> <equal> <quote>
:: Note that <lineFeed> and <equal> also causes problems, but are handled elsewhere
::
set "$write.temp=%temp%\writeTemp%random%"
copy nul "%$write.temp%.txt" /a >nul
for /f "usebackq" %%A in ("%$write.temp%.txt") do set "$write.sub=%%A"
del "%$write.temp%.txt"
for /f %%A in ('copy /z "%~f0" nul') do for /f %%B in ('cls') do (
set "$write.problemChars=%%A%%B ""
REM the characters after %%B above should be <space> <tab> <0xFF>
)
exit /b
echo | set /p dummyName=Hello World > somefile.txt
这将在打印的字符串末尾添加一个额外的空格,这可能会不方便,特别是因为我们试图避免在字符串末尾添加新行(另一个空白字符)。
幸运的是,引用要打印的字符串,即使用:
echo | set /p dummyName="Hello World" > somefile.txt
将不带任何换行符或空格字符的字符串打印出来。
World
和 >
之间没有放置空格,那么额外的空格应该消失。 - aschipflset /p="abc"<nul|xxd -p
显示616263
,而set /p=abc<nul|xxd -p
则给出61626320
。请注意,本文仅涉及翻译,不包含解释或其他内容。 - barlop解决SET /P中被剥离的空格问题:
关键在于回退字符,您可以在DOS文本编辑器EDIT中调用它。要在EDIT中创建它,请按ctrlP+ctrlH。我想在这里粘贴它,但是这个网页无法显示它。不过在记事本上可见(它很奇怪,像是一个带有白色圆圈的小黑色矩形)。
因此,您可以编写以下内容:
<nul set /p=.9 Hello everyone
点可以是任意字符,它只是告诉 SET /P 文本从那里开始,即在空格之前,而不是在“Hello”处开始。 “9”是退格符的表示形式,我无法在此处显示。您必须将其替换为 9,然后它将删除“.”,之后您将得到这个:
Hello Everyone
而不是:
Hello Everyone
我希望这对你有所帮助
这里介绍另一种方法,它使用Powershell Write-Host命令,该命令带有一个-NoNewLine参数,将其与start /b
结合使用,就可以从批处理中实现相同的功能。
NoNewLines.cmd
@ECHO OFF
start /b /wait powershell.exe -command "Write-Host -NoNewLine 'Result 1 - ';Write-Host -NoNewLine 'Result 2 - ';Write-Host -NoNewLine 'Result 3 - '"
PAUSE
输出
Result 1 - Result 2 - Result 3 - Press any key to continue . . .
@ECHO OFF
start /b /wait powershell.exe -command "Write-Host -NoNewLine 'Result 1 - '"
start /b /wait powershell.exe -command "Write-Host -NoNewLine 'Result 2 - '"
start /b /wait powershell.exe -command "Write-Host -NoNewLine 'Result 3 - '"
start /b /wait powershell.exe -command "Write-Host -NoNewLine 'Result 4 - '"
start /b /wait powershell.exe -command "Write-Host -NoNewLine 'Result 5 - '"
start /b /wait powershell.exe -command "Write-Host -NoNewLine 'Result 6 - '"
start /b /wait powershell.exe -command "Write-Host -NoNewLine 'Result 7 - '"
start /b /wait powershell.exe -command "Write-Host -NoNewLine 'Result 8 - '"
start /b /wait powershell.exe -command "Write-Host -NoNewLine 'Result 9 - '"
PAUSE
我根据@arnep的想法制作了一个函数:
echo|set /p="你好,世界"
这就是函数内容:
:SL (sameline)
echo|set /p=%1
exit /b
使用 call :SL "Hello There"
命令来调用。
我知道这没什么特别的,但我想了很久才想到它,所以我在这里发布了它。
你可以使用gnuwin32(coreutils软件包)中的“tr”命令来删除换行符。
@echo off
set L=First line
echo %L% | tr -d "\r\n"
echo Second line
pause
\r
、\n
或\r\n
(分别是OSX、Posix和Windows中的换行符)都不是“空格”字符。 - user66001printf
代替 echo
。 printf
默认不会发出换行符。 - Ross Smith IIcw.exe
(控制台写入)实用工具如果你找不到现成的、可用的,那么就 DYI 吧。使用此 cw
实用工具,您可以使用各种字符。至少我是这样认为的,请进行压力测试并让我知道。
您只需要安装.NET,这在今天是非常普遍的。
一些输入/复制粘贴的字符。
.bat
文件。/* >nul 2>&1
@echo off
setlocal
set exe=cw
for /f "tokens=* delims=" %%v in ('dir /b /s /a:-d /o:-n "%SystemRoot%\Microsoft.NET\Framework\*csc.exe"') do set "csc=%%v"
"%csc%" -nologo -out:"%exe%.exe" "%~f0"
endlocal
exit /b %errorlevel%
*/
using System;
namespace cw {
class Program {
static void Main() {
var exe = Environment.GetCommandLineArgs()[0];
var rawCmd = Environment.CommandLine;
var line = rawCmd.Remove(rawCmd.IndexOf(exe),exe.Length).TrimStart('"');
line = line.Length < 2 ? "\r" : line.Substring(2) ;
Console.Write(line);
}
}
}
运行它。
现在你拥有了一个漂亮的4KB实用程序,因此您可以删除.bat
文件。
或者,您可以将此代码作为子例程插入到任何批处理中,将生成的.exe
发送到%temp%
,在批处理中使用它,并在完成后将其删除。
如果您想写一些不带换行符的内容:
cw 无论您想要什么,甚至是带有"",但请记住转义^|、^^、^&等,除非像"| ^ &"中那样双引号引用。
如果您想进行回车(回到行的开头),只需运行
cw
所以从命令行尝试这个:
for /l %a in (1,1,1000) do @(cw ^|&cw&cw /&cw&cw -&cw&cw \&cw)
echo
可以使用-n
,但在cmd.exe
上它就是不起作用^^ - pannyecho
可以使用-n
”这条评论是不正确的。 - user66001