Batch di Windows: eco senza nuova riga


231

Qual è l'equivalente batch di Windows del comando shell Linux echo -nche sopprime la nuova riga alla fine dell'output?

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



2
questo mi ha fatto quasi impazzire.. sapevo che echopoteva accettarlo, -nma sul cmd.exefatto che non avrebbe funzionato ^^
panny

11
@panny - Nonostante il nome comune, echo non è lo stesso comando tra Windows e Posix. Come nslookup, ha diverse opzioni. Quindi il commento "Sapevo di echopoter prendere -n" nel contesto di una domanda relativa a Windows, non è corretto.
user66001,

Risposte:


236

Utilizzando sete il /pparametro è possibile eseguire l'eco senza newline:

C:\> echo Hello World
Hello World

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

fonte


86
La pipa è molto lenta in quanto crea due ulteriori compiti cmd, più veloce è <nul set /p =Hello. set /pnon può riecheggiare un segno uguale come primo carattere né spazi / tabulazioni.
Jeb

11
È quasi 15 volte più veloce sul mio sistema
jeb

28
Aggiungi virgolette intorno a "Hello World" per impedire lo spazio estraneo dopo la d.
Brian,

13
Attenzione: questo cambierà ERRORLEVEL in 1. Vedi la risposta di @xmechanix.
CoperNick,

6
@ user246694 < nulè un reindirizzamento dal NULdispositivo. Non contiene nulla, ma è sufficiente per set /psmettere di aspettare l'input dell'utente
jeb

100

Usando: echo | set /p=o <NUL set /p=funzioneranno entrambi per sopprimere la nuova riga.

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

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

Questo produrrà esattamente quello che vuoi senza che succeda qualcosa di subdolo in background, come ho dovuto scoprire nel modo più duro, ma funziona solo con la versione in pipe; <NUL set /p dummyName=Helloaumenterà ancora ERRORLEVEL a 1.


20
Avvertenza: questo comando imposterà ERRORLEVEL su 0. Se ERRORLEVEL era maggiore di 0, cambierà ERRORLEVEL su 0. Anche questo può essere pericoloso quando si scrivono script più avanzati. (ma +1 per la risposta)
CoperNick

Quindi in pratica hai bisogno di un IF ERRORLEVEL == 0 (...) ELSE (...) solo per non danneggiare il tuo ambiente in quelle circostanze. Sheesh.
SilverbackNet,

28

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

  • Le citazioni iniziali possono essere rimosse

  • Lo spazio bianco iniziale può essere rimosso

  • L'inizio =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 Output text senza avanzamento riga, anche con spazio iniziale o = Ho perfezionato il metodo in modo da poter 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 :writeInitializemetodo 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 :writee :writeVarsono ottimizzati in modo tale che solo le stringhe contenenti fastidiosi caratteri iniziali vengano scritte usando la mia versione modificata del metodo COPY di jeb. Le stringhe non problematiche vengono 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

1
Bello vedere una soluzione molto potente in grado di gestire tutti i personaggi
jeb

2
Vorrei sottolineare che, se il computer ha una connessione di rete a Internet, è possibile utilizzare all'incirca questa parte del codice batch per scaricare e installare Python o qualsiasi altra cosa sul computer che può eliminare il batch. Il batch è divertente, tuttavia le sue funzionalità di stringa sono le migliori per le sfide del fine settimana.
n611x007,

@dbenham on line 6 "echo (" è funzionalmente uguale a "echo." - non l'ho mai visto prima.
Salta R

2
@SkipR - Sì, è funzionalmente uguale a ECHO., tranne che ECHO.può fallire in circostanze oscure . Ci sono un sacco di altre forme che possono fallire anche in situazioni oscure. L'unico che funziona sempre è ECHO(.
dbenham,

10

Come addendum alla risposta di @ xmechanix, ho notato scrivendo il contenuto in un file:

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

Che ciò aggiungerà uno spazio extra alla fine della stringa stampata , il che può essere scomodo, specialmente perché stiamo cercando di evitare di aggiungere una nuova riga (un altro carattere di spazio) alla fine della stringa.

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

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

Stampa la stringa senza caratteri di nuova riga o spazio alla fine.


5
Lo spazio extra dovrebbe scomparire se non si inserisce uno spazio tra Worlde >...
aschipfl

@aschipfl Provato, non lo fa.
Joan Bruguera,

Il metodo della variabile quotata, una caratteristica non documentata del comando set, è in genere il modo in cui vedo che dovrebbe essere affrontato, poiché funziona in tutte le versioni di Windows NT (e 9x se ricordo). Cioè si racchiude il nome della variabile alla fine del valore tra virgolette. Questo vale anche per Set / P.
Ben Personick,

1
IE: echo | set / p "dummyName = Hello World"> somefile.txt
Ben Personick

2
@aschipfl Apparirà uno spazio extra se non fai le virgolette e fai una pipe. xxd è un'utilità di dump esadecimale, quindi vediamo ad esempio set /p="abc"<nul|xxd -pdisplay 616263 mentre set /p=abc<nul|xxd -p61626320
barlop il

9

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

il trucco è quel carattere backspace che puoi evocare nell'editor di testo EDIT per DOS. Per crearlo in MODIFICA, premi ctrlP + ctrlH . Vorrei incollarlo qui ma questa pagina Web non può visualizzarlo. Tuttavia è visibile sul Blocco note (è un po '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 a SET / P che il testo inizia lì, prima degli spazi, e non in " Ciao ". " 9 " è una 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


2
Ho dimenticato di dirlo, funziona in Windows 7 Non funzionerà in una riga di comando, solo in un batch. Per chiunque non ottenga il carattere, scarica questo esempio: pecm.com.sapo.pt/SET_with_backspace_char.txt
Pedro

Vero anche per Echo
Ben Personick il

... Quindi, dopo aver fatto una ricerca dannatamente approfondita, non ho trovato questo OVUNQUE in rete. Potrebbe essere l'unica volta in cui ho scoperto qualcosa, e per muta fortuna. Per chi non lo sapesse, PUOI inserire caratteri di controllo se metti il ​​tuo prompt cmd in modalità legacy e usi il carattere giusto. ... Ma se semplicemente reindirizzi qualcosa a un file o> con, funziona anche. Sul serio. Incollalo ESATTAMENTE nel tuo prompt dei comandi: "echo ← c◙◙ ○○ Harharhar !! ◙ ○○ ------------- ◙◙ ○○ Sono il peggiore!?: '(○ ♪ ○ NOPE! • ○ ○ Mi sento benissimo! Hazzah-le-oop! ◙◙ ○ Sono programmatore ascoltami ... qualcosa. ◙> con ".
Brent Rittenhouse

Ok, spero di averlo scoperto prima di chiunque altro, ma ... questo sembra dipendere dal fatto di non essere in una tabella codici Unicode. È possibile memorizzare quello iniziale in una variabile do chcp 437, impostare il set in una variabile o inviarlo in output, quindi tornare indietro (e dovrebbe comunque essere emesso). Ci sto ancora giocando.
Brent Rittenhouse,

Inoltre, qualcuno ha idea del perché ← c cancella lo schermo ?! Non riesco a trovarne un'istanza da nessuna parte sulla rete. È specificatamente quella combinazione, sebbene sembri essere in grado di avere spazi bianchi anche tra i due personaggi. Per qualsiasi altro personaggio sembra semplicemente ... rimuovere il primo personaggio. Non capisco ...
Brent Rittenhouse,

7

Puoi rimuovere la nuova riga usando "tr" da gnuwin32 ( pacchetto coreutils )

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

A proposito, se stai facendo un sacco di script, gnuwin32 è una miniera d'oro.


Suggerisco anche di installare git bash . sicuramente non è lo stesso di gnuwin32 (ed è quindi una miniera d'oro quindi +1), è solo una buona configurazione, e hai git-bash sul pulsante destro del mouse quasi ovunque, incluso il pulsante del menu Start.
Hakre,

puoi usare tr per rimuovere solo l'ultimo carattere spaziale, come in trim?
panny,

usa sed per trim: sed -e "s / * $ //"
BearCode

@panny - Non riesco a trovare un util posix / linux chiamato trim. Inoltre, \r, \no \r\n(Nuove linee in OSX, Posix e Windows, rispettivamente) non sono caratteri "spazio".
user66001

5

Ecco un altro metodo, usa Powershell Write-Host che ha un parametro -NoNewLine, combinalo con start /b e offre le stesse 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 qui sotto è leggermente diverso, non funziona esattamente come vuole l'OP, 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


2

Forse questo è quello che stai cercando, è una sceneggiatura della 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 riga 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é utilizza una variabile per uno scopo diverso da quello che si intende fare. come puoi vedere, "% bs%" rappresenta un backspace. Il secondo "% bs%" utilizza il backspace per aggiungere spazi dopo il "Messaggio di esempio" per separare l '"output del comando Pausa" senza aggiungere effettivamente un carattere visibile dopo il "Messaggio di esempio". Tuttavia, questo è possibile anche con un segno di percentuale regolare.


2
Vedo questo set nl=^& echo.trucco ovunque e il nome della variabile è fuorviante. % nl% non è un carattere di nuova riga : si espande in &echo.tal modo alla fine si esegue un nuovo echocomando ogni volta, quindi la nuova riga. Puoi verificarlo scrivendo echo "%nl%The%nl%new%nl%line%nl%is%nl%not%nl%apparent%nl%throughout%nl%text%nl%". Ottieni "& echo. The& echo. new& echo. line& echo. is& echo. not& echo. apparent& echo. throughout& echo. text& echo. ", rivelando il trucco. L'output è lo stesso ma non per i motivi che suggerisci.
cdlvcdlv,

2

Fai da te cw.exeUtilità (scrittura console)

Se non lo trovi pronto all'uso, pronto all'uso, puoi fare il fai-da-te. Con questocw utility puoi usare ogni tipo di personaggio. Almeno, mi piacerebbe pensarlo. Per favore, prova lo stress e fammi sapere.

Utensili

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

materiale

Alcuni caratteri digitati / incollati.

passi

  1. Crea un .batfile 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, è possibile inserire questo codice come subroutine in qualsiasi batch, inviare il risultato .exea %temp%, utilizzarlo nel batch ed eliminarlo al termine.

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 si desidera un ritorno a capo (andando all'inizio della riga), eseguire 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)

Sono stato ispirato dalla tua risposta e creato questo piccolo strumento con Go e questa attività di accompagnamento per Azure Pipeline. Cattura semplicemente lo stdout che viene reindirizzato e lo emette in un formato specifico per essere raccolto dalla build. Grazie!
riezebosch,

2

Ho creato una funzione dall'idea di @arnep:

echo | set / p = "Ciao mondo"

Ecco qui:

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

Usalo con call :SL "Hello There"
So che questo non è niente di speciale, ma mi ci è voluto tanto tempo a pensarci, ho pensato di pubblicarlo qui.


1

Esempio 1: funziona e produce un codice di uscita = 0. Va bene. 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 visualizzerebbe ... 0

Esempio 2: funziona ma produce un codice di uscita = 1. È negativo. 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 visualizzerebbe ... 1


1

Ispirato dalle risposte a questa domanda, ho creato un semplice script batch contatore che continua a stampare il valore di avanzamento (0-100%) sulla stessa riga (sovrascrivendo quella precedente). Forse questo sarà prezioso anche per gli altri che cercano una soluzione simile.

Nota : si *tratta di caratteri non stampabili, che devono essere immessi utilizzando la combinazione di tasti [ Alt+ Numpad 0+ Numpad 8], che è il backspacecarattere.

@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

0

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

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

3
Questo stamperà comunque una nuova riga.
René Nyffenegger,

3
Puoi concatenare sulla stessa variabile quanto vuoi e fare eco solo alla fine.
m0skit0,

2
Stamparlo quando si esegue il ciclo o alla fine non importa se i dati vengono conservati. Per ogni ciclo è sufficiente concatenare i dati, quindi al termine del ciclo è possibile stamparli. Il risultato è lo stesso.
m0skit0,

9
Si fa importa se si tratta di un indicatore della progressione del ciclo.
Gregregh,

3
Non hai mai dichiarato che nella tua domanda o richiesto questo comportamento ovunque nella tua domanda.
m0skit0,

0

Puoi sopprimere la nuova riga usando 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 da poter 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 usare anche 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 anziché quello. Spero che tu non abbia l'uso del punto esclamativo "!" ;)


-1

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


@jiggunjer Sei sicuro? printfing da un cmdriquadro Win-7 mi dà"'printf' is not recognized as an internal or external command, operable program or batch file."
SeldomNeedy

printfnon è nativo di Windows. Questa è una domanda di Windows.
kayleeFrye_onDeck,

1
@kayleeFrye_onDeck Suppongo che il tuo commento sia diretto a Jiggunjer , non a me; Suggerisco nella mia domanda che C e C ++ potrebbero essere usati come un'alternativa abbastanza indipendente dalla piattaforma ai comandi della shell nei casi in cui la formattazione è importante.
SeldomNeedy,

1
Perdonami padre, perché ho scremato.
kayleeFrye_onDeck,

Ma quindi l'input per la shell deve essere analizzato correttamente. Ad esempio, come può un programma simile stampare le virgolette?
Alex
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.