簡體   English   中英

Windows 批處理:echo 沒有換行

[英]Windows batch: echo without new line

什么是 Linux shell 命令echo -n的 Windows 批處理等效項,它在輸出的末尾抑制換行符?

這個想法是在循環內的同一行上寫。

使用set/p參數,您可以在沒有換行符的情況下進行回顯:

C:\> echo Hello World
Hello World

C:\> echo|set /p="Hello World"
Hello World
C:\>

來源

使用: echo | 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

這將在打印的 string 末尾添加一個額外的空格,這可能很不方便,特別是因為我們試圖避免在字符串末尾添加新行(另一個空格字符)。

幸運的是,引用要打印的字符串,即使用:

echo | set /p dummyName="Hello World" > somefile.txt

將打印末尾沒有任何換行符或空格字符的字符串。

SET /P 中去除空白的解決方案:

訣竅是,退格字符,你可以在文本編輯器編輯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 是一個金礦。

這是另一種方法,它使用具有 -NoNewLine 參數的 Powershell Write-Host,將其與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

DIY cw.exe (控制台寫入)實用程序

如果您沒有發現它是開箱即用的,您可以自己動手做。 使用此cw實用程序,您可以使用各種字符。 至少,我願意這么認為。 請對其進行壓力測試並讓我知道。

工具

您只需要安裝.NET ,這在當今非常普遍。

材料

輸入/復制粘貼的一些字符。

腳步

  1. 使用以下內容創建.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);
        }
    }
}
  1. 運行。

  2. 現在您有一個不錯的 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)

我根據@arnep 的想法做了一個函數:

echo|set /p="Hello World"

這里是:

:SL (sameline)
echo|set /p=%1
exit /b

將其與call :SL "Hello There"
我知道這沒什么特別的,但我花了很長時間才想到它,我想我會把它貼在這里。

這里

<nul set /p =Testing testing

並且還以空格開頭的 echo 使用

echo.Message goes here

也許這就是你要找的,這是一個老派的劇本......: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%”使用退格鍵在“示例消息”之后添加空格來分隔“暫停命令的輸出”,而實際上並未在“示例消息”之后添加可見字符。 但是,這也可以使用常規百分比符號。

示例 1:這有效並產生退出代碼 = 0。那很好。 注意“.” , 直接在 echo 之后。

C:\\Users\\phife.dog\\gitrepos\\1\\repo_abc\\scripts #
@回聲。| set /p JUNK_VAR=這是一條顯示的消息,就像 Linux echo -n 會顯示它...... & echo %ERRORLEVEL%

這是一條顯示的消息,就像 Linux echo -n 會顯示它... 0

示例 2:這有效,會產生退出代碼 = 1。這是錯誤的。 請注意在 echo 之后缺少“.”。 這似乎就是區別。

C:\\Users\\phife.dog\\gitrepos\\1\\repo_abc\\scripts #
@回聲| 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 /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 命令無法識別“!” 字符並打印一個點而不是那個。 我希望你沒有使用感嘆號“!” ;)

使用比爾·斯圖爾特( Bill Stewart)出色的“Shell Scripting Toolkit”中的 EchoX.EXE
如何在 Windows Cmd 腳本中取消換行:

@Echo Off
Rem Print three Echos in one line of output
EchoX -n "Part 1 - "
EchoX -n "Part 2 - "
EchoX    "Part 3"
Rem

給出:

Part 1 - Part 2 - Part 3
{empty line}
d:\Prompt>

這種用法的幫助是:

Usage: echox [-n] message
  -n       Do not skip to the next line.
  message  The text to be displayed.

該實用程序小於 48K,應該存在於您的路徑中。 它可以做的更多事情:
- 打印文本而不移動到下一行
- 在一定寬度內打印向左、居中或向右對齊的文本
- 打印帶有制表符、換行符和回車符的文本
- 以前景色和背景色打印文本

該工具包包括另外十二個很棒的腳本技巧。
下載頁面還包含其他三個有用的工具包。

方法如下: <nul set /p="Your Text"

帶有前面的空格且不帶換行符的回顯

正如Pedro之前所說, echo 沒有換行並且前面有空格(前提是 "9" 是一個真正的 [BackSpace])。

<nul set /p=.9    Hello everyone

我在使用新控制台在 Windows 10 中使用它時遇到了一些問題,但通過以下方式進行了管理。
在 CMD 類型中:

echo .◘>bs.txt

按 [Alt] + [8] 得到“◘”
(實際符號可能因代碼頁而異)。

然后很容易使用 Notepad.exe 將結果從“bs.txt”復制到需要的地方。

@echo off
<nul set /p "_s=.◘    Hello everyone"
echo: here

使用 jscript:

@if (@X)==(@Y) @end /*
    @cscript //E:JScript //nologo "%~nx0" %*
    @exit /b %errorlevel%
*/if(WScript.Arguments.Count()>0) WScript.StdOut.Write(WScript.Arguments.Item(0));

如果它被稱為 write.bat 你可以像這樣測試它:

call write.bat string & echo _Another_String_

如果您想使用 powershell 但使用 cmd 定義的變量,您可以使用:

set str=_My_StrinG_
powershell "Write-Host -NoNewline ""%str%""""  & echo #Another#STRING#

我發現這個名為“EchoPart.bat”的簡單單行批處理文件非常有用。

@echo | set /p=%*

然后我甚至可以在交互式 CMD 行上或作為快捷方式的一部分編寫類似下面的內容。 它開辟了一些新的可能性。

echopart "Hello, " & echopart "and then " & echo Goodbye

在此處輸入圖片說明

如果您在批處理文件中使用它,則可以從參數變量而不是不可變字符串中獲取文本。 例如:

@echopart Hello %* & @echo , how are you?

因此,在“SayHello.bat”中執行這一行允許:

在此處輸入圖片說明

甚至...

在此處輸入圖片說明

玩得開心,玩得開心!

我相信沒有這樣的選擇。 或者你可以試試這個

set text=Hello
set text=%text% world
echo %text%

遲到的答案,但對於任何需要將特殊字符寫入一行的人來說,他們發現dbenham的答案太長了大約 80 行,並且在簡單地使用set /p的限制下,他們的腳本可能會中斷(可能是由於用戶輸入) set /p ,將您的 .bat 或 .cmd 與編譯的 C++ 或 C 語言可執行文件配對,然后只是coutprintf字符,這可能是最簡單的。 如果您顯示某種進度條或使用字符的東西,這也將允許您輕松地多次寫入一行,就像 OP 顯然那樣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM