Windows批处理等效于Linux shell命令echo -n
,该命令在输出末尾取消换行符?
想法是在循环内的同一行上编写。
echo
可以采取-n
,但是,cmd.exe
它是做不到的^^
echo
可以接受-n
” 的注释是错误的。
Windows批处理等效于Linux shell命令echo -n
,该命令在输出末尾取消换行符?
想法是在循环内的同一行上编写。
echo
可以采取-n
,但是,cmd.exe
它是做不到的^^
echo
可以接受-n
” 的注释是错误的。
Answers:
使用set
和/p
参数,您可以不使用换行符进行回显:
C:\> echo Hello World
Hello World
C:\> echo|set /p="Hello World"
Hello World
C:\>
<nul set /p =Hello
。set /p
不能与第一个字符或空格/制表符呼应等号。
< nul
是从NUL
设备的重定向。它不包含任何内容,但是足以set /p
停止等待用户输入
使用:echo | set /p=
或<NUL set /p=
都可以取消换行符。
但是,这在检查ERRORLEVEL变得很重要时编写更高级的脚本时非常危险,因为set /p=
未指定变量名的设置会将ERRORLEVEL设置为1。
更好的方法是只使用伪变量名,如下所示:
echo | set /p dummyName=Hello World
这将产生您想要的东西,而无需在后台进行任何麻烦的工作,因为我不得不找出困难的方法,但这仅适用于管道版本。<NUL set /p dummyName=Hello
仍会将ERRORLEVEL提高到1。
简单的SET / P方法的限制在Windows版本之间略有不同。
前导报价可能会被删除
前导空白可能会被剥夺
前导=
会导致语法错误。
有关更多信息,请参见http://www.dostips.com/forum/viewtopic.php?f=3&t=4209。
jeb发布了一个聪明的解决方案,即使没有空格或=,也可以解决输出文本中的大多数问题,而无需换行我也我改进了该方法,以便它可以在任何版本的Windows上安全地打印任何有效的批处理字符串而无需换行从XP开始。请注意,该:writeInitialize
方法包含的字符串文字可能无法很好地发布到站点。包含一个备注,描述了字符序列应该是什么。
对: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
作为@xmechanix答案的附录,我通过将内容写入文件来注意到:
echo | set /p dummyName=Hello World > somefile.txt
这样会在打印字符串的末尾添加额外的空间,这可能是不方便的,特别是因为我们试图避免在字符串的末尾添加新行(另一个空白字符)。
幸运的是,引用要打印的字符串,即使用:
echo | set /p dummyName="Hello World" > somefile.txt
将在末尾打印不带任何换行符或空格字符的字符串。
World
和之间不加空格,则多余的空间应会消失>
...
set /p="abc"<nul|xxd -p
显示616263
而 set /p=abc<nul|xxd -p
给出61626320
SET / P中剥离的空格的解决方案:
诀窍是可以在文本编辑器EDIT for DOS 中调用退格字符。要在EDIT中创建它,请按ctrlP + ctrlH。我将其粘贴在此处,但此网页无法显示。尽管它在记事本上可见(它很弯曲,就像一个小的黑色矩形,中间有一个白色的圆圈)
所以你这样写:
<nul set /p=.9 Hello everyone
点可以是任何字符,只能在其中告诉SET / P文本从空格开始,而不是在“ Hello ”处开始。“ 9 ”表示退格字符的表示,在这里我无法显示。您必须放置它而不是9,它会删除“ 。 ”,然后您将得到:
Hello Everyone
代替:
Hello Everyone
希望对您有所帮助
您可以从gnuwin32(coreutils软件包)中使用“ tr”删除换行符
@echo off
set L=First line
echo %L% | tr -d "\r\n"
echo Second line
pause
顺便说一句,如果您要编写大量脚本,那么gnuwin32是金矿。
trim
吗?
\r
,\n
或\r\n
(分别在OSX,POSIX和新的Windows线)不是“空间”字符。
这是另一种方法,它使用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 . . .
下面的内容略有不同,不能完全按照OP的要求来工作,但是很有趣,因为每个结果都将模拟一个计数器而覆盖先前的结果。
@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
也许这就是您想要的,这是一个古老的脚本...:P
set nl=^& echo.
echo %nl%The%nl%new%nl%line%nl%is%nl%not%nl%apparent%nl%throughout%nl%text%nl%
echo only in prompt.
pause
还是您尝试替换当前行而不是写新行?您可以通过删除“”之后的“%bs%”来进行实验。符号,并在“示例消息”之后将其他“%bs%”隔开。
for /f %%a in ('"prompt $H&for %%b in (1) do rem"') do set "bs=%%a"
<nul set /p=.%bs% Example message %bs%
pause
我发现这真的很有趣,因为它使用变量的目的不是目的。如您所见,“%bs%”表示退格键。第二个“%bs%”使用空格在“示例消息”之后添加空格,以分隔“暂停命令的输出”,而没有实际在“示例消息”之后添加可见字符。但是,使用常规百分号也是可能的。
set nl=^& echo.
到处都看到了这个窍门,变量的名称令人误解。%NL%的不换行字符:它扩大到&echo.
所以最后你正在运行一个新的echo
每一次命令,因此换行符。您可以检查出来写echo "%nl%The%nl%new%nl%line%nl%is%nl%not%nl%apparent%nl%throughout%nl%text%nl%"
。您得到了"& echo. The& echo. new& echo. line& echo. is& echo. not& echo. apparent& echo. throughout& echo. text& echo. "
,揭示了窍门。输出是相同的,但并非出于您建议的原因。
cw.exe
(控制台写入)实用程序如果找不到现成的现成产品,则可以进行DIY。使用此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 Whatever you want, even with "", but remember to escape ^|, ^^, ^&, etc. unless double-quoted, like in "| ^ &".
如果要回车(转到行的开头),只需运行
cw
因此,请从命令行尝试以下操作:
for /l %a in (1,1,1000) do @(cw ^|&cw&cw /&cw&cw -&cw&cw \&cw)
示例1:这有效并产生退出代码=0。很好。注意“。” ,直接在回声之后。
C:\ Users \ phife.dog \ gitrepos \ 1 \ repo_abc \ scripts#@echo
。| set / p JUNK_VAR =这是一条像Linux echo一样显示的消息-n将显示它...&echo%ERRORLEVEL%
这是一条像Linux echo -n一样显示的消息... 0
示例2:可以,但是生成退出代码=1。这很糟糕。回音后请注意缺少“。”。这似乎是有区别的。
C:\ Users \ phife.dog \ gitrepos \ 1 \ repo_abc \ scripts#@echo
| set / p JUNK_VAR =这是一条像Linux echo一样显示的消息-n将显示它...&echo%ERRORLEVEL%
这是一条像Linux echo -n一样显示的消息... 1
受此问题答案的启发,我制作了一个简单的计数器批处理脚本,该脚本始终在同一行上打印进度值(0-100%)(覆盖上一个)。也许这对于其他寻求类似解决方案的人也很有价值。
备注:*
属于不可打印字符,应使用[ Alt
+ Numpad 0
+ Numpad 8
]组合键输入这些backspace
字符。
@ECHO OFF
FOR /L %%A in (0, 10, 100) DO (
ECHO|SET /P="****%%A%%"
CALL:Wait 1
)
GOTO:EOF
:Wait
SET /A "delay=%~1+1"
CALL PING 127.0.0.1 -n %delay% > NUL
GOTO:EOF
我相信没有这样的选择。另外,您可以尝试一下
set text=Hello
set text=%text% world
echo %text%
您可以使用set / p命令取消换行。set / p命令不能识别空格,因为您可以使用点和退格字符使其识别。您还可以将变量用作存储器并在其中存储要打印的内容,以便可以打印变量而不是句子。例如:
@echo off
setlocal enabledelayedexpansion
for /f %%a in ('"prompt $H & for %%b in (1) do rem"') do (set "bs=%%a")
cls
set "var=Hello World! :)"
set "x=0"
:loop
set "display=!var:~%x%,1!"
<nul set /p "print=.%bs%%display%"
ping -n 1 localhost >nul
set /a "x=%x% + 1"
if "!var:~%x%,1!" == "" goto end
goto loop
:end
echo.
pause
exit
这样,您可以打印任何内容而无需换行。我已经制作了程序来逐个打印字符,但是通过更改循环,您也可以使用单词代替字符。
在上面的示例中,我使用了“ enabledelayedexpansion”,因此set / p命令无法识别“!”。字符并打印一个点代替它。希望您不要使用感叹号“!” ;)
这里的答案很晚,但是对于需要在一行中写特殊字符的人来说, dbenham的答案太长了80行,并且在简单使用的限制下,其脚本可能会中断(也许由于用户输入)set /p
,它可能最容易只是配对.bat或与编译的C ++或C语言可执行.CMD,然后只cout
或printf
字符。如果您正在显示某种进度条或某些使用字符的东西(如OP一样),这也将使您可以轻松地多次写入一行。
printf
在Win-7 cmd
窗格中"'printf' is not recognized as an internal or external command, operable program or batch file."
printf
不是Windows固有的。这是一个Windows问题。