risposta-alla-domanda-sullo-sviluppo-web-bd.com

Batch di Windows: echo senza nuova riga

Qual è l'equivalente in batch di Windows del comando shell di Linux echo -n che sopprime il newline alla fine dell'output?

L'idea è di scrivere sulla stessa riga all'interno di un ciclo.

188
gregseth

Usando set e il parametro /p puoi echo senza newline:

C:\> echo Hello World
Hello World

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

Fonte

197
arnep

L'utilizzo di: echo | set /p= o <NUL set /p= funzionerà entrambi per sopprimere la nuova riga.

Tuttavia, questo può essere molto pericoloso quando si scrivono script più avanzati quando si controlla che ERRORLEVEL diventi importante poiché l'impostazione set /p= senza specificare un nome di variabile imposterà ERRORLEVEL su 1.

Un approccio migliore sarebbe semplicemente utilizzare un nome di variabile fittizio in questo modo:
echo | set /p dummyName=Hello World 

Questo produrrà esattamente quello che vuoi senza che nulla di subdolo possa succedere in sottofondo mentre dovevo scoprire la via difficile, ma questo funziona solo con la versione con piping; <NUL set /p dummyName=Hello aumenterà ancora ERRORLEVEL a 1.

85
xmechanix

Il semplice metodo SET/P presenta limitazioni che variano leggermente tra le versioni di Windows.

  • Le citazioni principali possono essere spogliate

  • Lo spazio bianco principale può essere rimosso

  • Il codice = principale causa un errore di sintassi.

Vedi http://www.dostips.com/forum/viewtopic.php?f=3&t=4209 per ulteriori informazioni.

jeb ha pubblicato una soluzione intelligente che risolve la maggior parte dei problemi in Testo di output senza linefeed, anche con spazio iniziale o = Ho perfezionato il metodo in modo che possa stampare in modo sicuro qualsiasi stringa batch valida senza la nuova riga, su qualsiasi versione di Windows da XP in poi. Si noti che il metodo :writeInitialize contiene una stringa letterale che potrebbe non essere pubblicata correttamente sul sito. È inclusa un'osservazione che descrive quale dovrebbe essere la sequenza di caratteri.

I metodi :write e :writeVar sono ottimizzati in modo tale che solo le stringhe contenenti caratteri di primo piano fastidiosi vengano scritti utilizzando la mia versione modificata del metodo COPY di jeb. Le stringhe non problematiche sono scritte usando il metodo SET/P più semplice e veloce.

@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
25
dbenham

Una soluzione per lo spazio bianco spogliato in SET/P:

il trucco è il carattere backspace che puoi richiamare nell'editor di testo EDIT per DOS. Per crearlo in EDIT, premi ctrlP + ctrlH . Lo incollerei qui ma questa pagina web non può visualizzarlo. È visibile sul blocco note (è werid, come un piccolo rettangolo nero con un cerchio bianco al centro)

Quindi scrivi questo:

<nul set /p=.9    Hello everyone

Il punto può essere qualsiasi carattere, è solo lì per dire SET/P che il testo inizia lì, prima degli spazi, e non al "Hello" . Il " 9 " è un rappresentazione del carattere backspace che non posso visualizzare qui. Devi metterlo al posto del 9, e cancellerà il ". ", dopo di che otterrai questo:

    Hello Everyone

invece di:

Hello Everyone

Spero possa essere d'aiuto

9
Pedro

Come addendum alla risposta di @ xmechanix, ho notato attraverso la scrittura del contenuto in un file:

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

Questo aggiungerà uno spazio extra alla fine della stringa stampata , che può essere sconveniente, specialmente visto che stiamo cercando di evitare di aggiungere una nuova riga (un altro carattere di spaziatura) alla fine della stringa.

Fortunatamente, citando la stringa da stampare, cioè utilizzando:

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

Stamperà la stringa senza alcun carattere di fine riga o spazio alla fine.

8
Joan Bruguera

Puoi rimuovere il newline usando "tr" da gnuwin32 ( coreutils package)

@echo off
set L=First line
echo %L% | tr -d "\r\n"
echo Second line
pause

A proposito, se stai facendo molti script, gnuwin32 è una miniera d'oro.

7
BearCode

Ecco un altro metodo, utilizza Powershell Write-Host che ha un parametro -NoNewLine, che combina quello con start /b e offre la stessa funzionalità dal batch.

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

Produzione

Result 1 - Result 2 - Result 3 - Press any key to continue . . .

Questo sotto è leggermente diverso, non funziona esattamente come l'OP vuole, ma è interessante perché ogni risultato sovrascrive il risultato precedente emulando un contatore.

@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
5
Knuckle-Dragger

Da qui

<nul set /p =Testing testing

e anche per echo a partire dall'uso degli spazi

echo.Message goes here

Utilità cw.exe (console di scrittura) fai-da-te

Se non lo trovi subito pronto per l'uso, puoi fare il fai-da-te. Con questa utility cw puoi usare ogni tipo di carattere. Almeno, mi piacerebbe pensarlo. Si prega di stress-test e fammi sapere.

Utensili

Tutto ciò che serve è . NET installato, che è molto comune al giorno d'oggi.

Materiale

Alcuni caratteri digitati/copiati.

Passi

  1. Creare il file .bat con il seguente contenuto.
/* >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. Eseguirlo.

  2. Ora hai una bella utility 4KB in modo da poter eliminare .bat.

In alternativa, puoi inserire questo codice come subroutine in qualsiasi batch, inviare il .exe risultante a %temp%, usarlo nel tuo batch ed eliminarlo quando hai finito.

Come usare

Se vuoi scrivere qualcosa senza una nuova riga:
cw Whatever you want, even with "", but remember to escape ^|, ^^, ^&, etc. unless double-quoted, like in "| ^ &".

Se vuoi un ritorno a capo (andando all'inizio della riga), esegui solo
cw

Quindi prova questo dalla riga di comando:

for /l %a in (1,1,1000) do @(cw ^|&cw&cw /&cw&cw -&cw&cw \&cw)
2
cdlvcdlv

Forse questo è quello che stai cercando, è una sceneggiatura vecchia scuola ...: 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

o forse stai cercando di sostituire una linea corrente invece di scrivere su una nuova riga? puoi sperimentare rimuovendo "% bs%" dopo "." firmare e anche distanziando l'altro "% bs%" dopo il "Messaggio di esempio".

for /f %%a in ('"Prompt $H&for %%b in (1) do rem"') do set "bs=%%a"
<nul set /p=.%bs%         Example message         %bs%
pause

Lo trovo davvero interessante perché usa una variabile per uno scopo diverso da quello che è destinato a fare. come puoi vedere il "% bs%" rappresenta un backspace. Il secondo "% bs%" utilizza il backspace per aggiungere spazi dopo il "Messaggio di esempio" per separare "l'output del comando di pausa" senza aggiungere effettivamente un carattere visibile dopo il "messaggio di esempio". Tuttavia, questo è anche possibile con un segno percentuale regolare. 

2
zask

Esempio 1: funziona e produce codice di uscita = 0. È buono. Notare la "." , direttamente dopo l'eco.

C:\Users\phife.dog\gitrepos\1\repo_abc\scripts #
@echo. | set/p JUNK_VAR = Questo è un messaggio visualizzato come Linux echo -n lo visualizzerebbe ... & echo% ERRORLEVEL%

Questo è un messaggio visualizzato come Linux echo -n lo mostrerebbe ... 0

Esempio 2: Funziona ma produce Codice di uscita = 1. Che è cattivo. Si noti la mancanza di ".", Dopo l'eco. Questa sembra essere la differenza.

C:\Users\phife.dog\gitrepos\1\repo_abc\scripts #
@echo | set/p JUNK_VAR = Questo è un messaggio visualizzato come Linux echo -n lo visualizzerebbe ... & echo% ERRORLEVEL%

Questo è un messaggio visualizzato come Linux echo -n lo mostrerebbe ... 1 

1
user3175529

Risposta tardiva qui, ma per chiunque abbia bisogno di scrivere caratteri speciali su una singola riga che trova la risposta di dbenham è di circa 80 righe troppo lunghe e le cui sceneggiature potrebbero rompersi (forse a causa di input dell'utente) sotto le limitazioni semplicemente usando set /p, è probabilmente più semplice accoppiare il tuo .bat o .cmd con un eseguibile compilato in C++ o in linguaggio C e quindi solo cout o printf i caratteri. Questo ti permetterà anche di scrivere più volte su una riga se stai mostrando una sorta di barra di avanzamento o qualcosa usando i caratteri, come era apparentemente OP.

0
SeldomNeedy

Credo che non ci sia questa opzione. In alternativa puoi provare questo

set text=Hello
set text=%text% world
echo %text%
0
m0skit0

È possibile sopprimere la nuova riga utilizzando il comando set/p. Il comando set/p non riconosce uno spazio, per questo puoi usare un punto e un carattere backspace per farlo riconoscere. È inoltre possibile utilizzare una variabile come memoria e memorizzare ciò che si desidera stampare al suo interno, in modo che sia possibile stampare la variabile anziché la frase. Per esempio:

@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

In questo modo puoi stampare qualsiasi cosa senza una nuova riga. Ho creato il programma per stampare i caratteri uno per uno, ma puoi anche usare le parole anziché i caratteri cambiando il ciclo.

Nell'esempio sopra ho usato "enabledelayedexpansion" quindi il comando set/p non riconosce "!" carattere e stampa un punto invece di quello. Spero che tu non abbia l'uso del punto esclamativo "!" ;)

Ho realizzato una funzione dall'idea di @arnep: 

echo | set/p = "Hello World" 

Ecco qui:

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

Usalo con call :SL "Hello There"
So che questo non è niente di speciale ma ci ho messo così tanto tempo per pensarci che ho pensato di pubblicarlo qui.

0
Mark Deven