Lot Windows: écho sans nouvelle ligne


231

Quel est l'équivalent par lots Windows de la commande shell Linux echo -nqui supprime la nouvelle ligne à la fin de la sortie?

L'idée est d'écrire sur la même ligne à l'intérieur d'une boucle.



2
cela m'a rendu presque fou .. Je savais que ça echopourrait prendre -nmais cmd.exeça ne marcherait tout simplement pas ^^
panny

11
@panny - Malgré le nom commun, echo n'est pas la même commande entre Windows et Posix. Comme nslookup, il a différentes options. Ainsi, le commentaire "Je savais que je echopourrais prendre -n" dans le contexte d'une question concernant Windows est incorrect.
user66001

Réponses:


236

En utilisant setet le /pparamètre, vous pouvez faire écho sans nouvelle ligne:

C:\> echo Hello World
Hello World

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

La source


86
Le tuyau est très lent car il crée deux tâches cmd supplémentaires, plus rapide <nul set /p =Hello. set /pne peut pas faire écho à un signe égal comme premier caractère ni à des espaces / tabulations.
jeb

11
C'est presque 15 fois plus rapide sur mon système
jeb

28
Ajoutez des guillemets autour de "Hello World" pour empêcher l'espace superflu après le d.
Brian

13
Avertissement: Cela changera ERRORLEVEL à 1. Voir la réponse de @xmechanix.
CoperNick

6
@ user246694 < nulest une redirection depuis l' NULappareil. Il ne contient rien, mais cela suffit pour set /parrêter d'attendre la saisie de l'utilisateur
jeb

100

Utiliser: echo | set /p=ou <NUL set /p=fonctionnera tous les deux pour supprimer la nouvelle ligne.

Cependant, cela peut être très dangereux lors de l'écriture de scripts plus avancés lorsque la vérification du NIVEAU D'ERREUR devient importante car le réglage set /p=sans spécifier de nom de variable mettra le NIVEAU D'ERREUR à 1.

Une meilleure approche serait d'utiliser simplement un nom de variable factice comme ceci:
echo | set /p dummyName=Hello World

Cela produira exactement ce que vous voulez sans aucun truc sournois en arrière-plan car j'ai dû découvrir à la dure, mais cela ne fonctionne qu'avec la version piped; <NUL set /p dummyName=Helloaugmentera toujours le NIVEAU D'ERREUR à 1.


20
Avertissement: Cette commande définira ERRORLEVEL à 0. Si ERRORLEVEL était supérieur à 0, cela changera ERRORLEVEL à 0. Cela peut également être dangereux lors de l'écriture de scripts plus avancés. (mais +1 pour la réponse)
CoperNick

Donc, vous avez essentiellement besoin d'un IF ERRORLEVEL == 0 (...) ELSE (...) juste pour ne pas nuire à votre environnement dans ces circonstances. Sheesh.
SilverbackNet

28

La méthode SET / P simple a des limitations qui varient légèrement entre les versions de Windows.

  • Les citations principales peuvent être supprimées

  • Les espaces blancs de tête peuvent être supprimés

  • Le début =entraîne une erreur de syntaxe.

Voir http://www.dostips.com/forum/viewtopic.php?f=3&t=4209 pour plus d'informations.

jeb a publié une solution intelligente qui résout la plupart des problèmes de texte de sortie sans saut de ligne, même avec un espace au début ou = j'ai affiné la méthode afin qu'elle puisse imprimer en toute sécurité absolument n'importe quelle chaîne de lots valide sans la nouvelle ligne, sur n'importe quelle version de Windows à partir de XP. Notez que la :writeInitializeméthode contient un littéral de chaîne qui peut ne pas s'afficher correctement sur le site. Une remarque est incluse qui décrit la séquence de caractères.

Les méthodes :writeet :writeVarsont optimisées de telle sorte que seules les chaînes contenant des caractères principaux gênants sont écrites à l'aide de ma version modifiée de la méthode COPY de jeb. Les chaînes non gênantes sont écrites à l'aide de la méthode SET / P plus simple et plus rapide.

@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
Agréable de voir une solution très puissante qui peut gérer tous les personnages
jeb

2
Je voudrais souligner que si l'ordinateur dispose d'une connexion réseau à Internet, une grande partie du code de lot peut être utilisée pour télécharger et installer python ou toute autre chose sur l'ordinateur qui peut vous débarrasser du lot. Le lot est amusant, mais ses capacités de cordes sont les meilleures pour le défi du week-end.
n611x007

@dbenham sur la ligne 6 "echo (" est-ce la même chose que "echo"? - pas vu auparavant.
Ignorer R

2
@SkipR - Oui, il est fonctionnellement le même que ECHO., sauf qu'il ECHO.peut échouer dans des circonstances obscures . Il existe un tas d'autres formes qui peuvent également échouer dans des situations obscures. Le seul qui fonctionne toujours est ECHO(.
dbenham

10

En complément de la réponse de @ xmechanix, j'ai remarqué en écrivant le contenu dans un fichier:

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

Cela ajoutera un espace supplémentaire à la fin de la chaîne imprimée , ce qui peut être gênant, d'autant plus que nous essayons d'éviter d'ajouter une nouvelle ligne (un autre caractère d'espacement) à la fin de la chaîne.

Heureusement, en citant la chaîne à imprimer, c'est-à-dire en utilisant:

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

Imprime la chaîne sans aucun caractère de nouvelle ligne ou d'espace à la fin.


5
L'espace supplémentaire devrait disparaître si vous ne mettez pas d'espace entre Worldet >...
aschipfl

@aschipfl J'ai essayé, ce n'est pas le cas.
Joan Bruguera

La méthode variable citée, une fonction non documentée de la commande set, est généralement la façon dont je vois qu'elle doit être abordée, car elle fonctionne dans toutes les versions de WIndows NT (et 9x si je me souviens). C'est-à-dire que vous enveloppez le nom de la variable à la fin de la valeur entre guillemets. Cela est également vrai pour Set / P.
Ben Personick

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

2
@aschipfl Un espace supplémentaire apparaîtra si vous ne faites pas de guillemets et que vous faites un tuyau. xxd est un utilitaire de vidage hexadécimal, donc nous voyons par exemple les set /p="abc"<nul|xxd -paffichages 616263 alors que set /p=abc<nul|xxd -pdonne61626320
barlop

9

Une solution pour l'espace blanc dépouillé dans SET / P:

l'astuce est ce caractère de retour arrière que vous pouvez invoquer dans l'éditeur de texte EDIT for DOS. Pour le créer dans EDIT, appuyez sur ctrlP + ctrlH . Je le collerais ici mais cette page Web ne peut pas l'afficher. Il est cependant visible sur le bloc-notes (il était plus sec, comme un petit rectangle noir avec un cercle blanc au centre)

Vous écrivez donc ceci:

<nul set /p=.9    Hello everyone

Le point peut être n'importe quel caractère, il n'est là que pour indiquer à SET / P que le texte commence là, avant les espaces, et non au " Bonjour ". Le " 9 " est une représentation du caractère de retour arrière que je ne peux pas afficher ici. Vous devez le mettre à la place du 9, et il supprimera le " . ", Après quoi vous obtiendrez ceci:

    Hello Everyone

au lieu de:

Hello Everyone

J'espère que ça aide


2
J'ai oublié de le dire, cela fonctionne sous Windows 7 Cela ne fonctionnera pas en ligne de commande, seulement en batch. Pour ceux qui n'obtiennent pas le caractère, téléchargez cet exemple: pecm.com.sapo.pt/SET_with_backspace_char.txt
Pedro

Également vrai pour Echo
Ben Personick

... Donc, après avoir fait une recherche sacrément approfondie, je n'ai trouvé cela nulle part sur le net. C'est peut-être la seule fois où j'ai réellement découvert quelque chose, et par une stupide chance. Pour ceux qui ne vous connaissent pas, vous pouvez entrer des caractères de contrôle si vous mettez votre invite cmd en mode hérité et utilisez la bonne police. ... Mais si vous redirigez simplement n'importe quoi vers un fichier ou> con, cela fonctionne aussi. Sérieusement. Collez ceci EXACTEMENT dans votre invite de commande: "echo ← c◙◙ ○○ Harharhar !! ◙ ○○ ------------- ◙◙ ○○ Je suis le pire!?: '(○ ♪ ○ NOPE! • ♪ ○ Je me sens bien! Hazzah-le-oop! ◙◙ ○ Je suis programmeur entendez-moi ... quelque chose.◙> con ".
Brent Rittenhouse

D'accord, j'espère avoir découvert cela avant tout le monde mais ... cela dépend apparemment de ne pas être dans une page de code Unicode. Vous pouvez stocker celui de départ dans une variable do chcp 437, définir l'ensemble dans une variable, ou le sortir, puis revenir en arrière (et il devrait toujours sortir). Je joue toujours avec.
Brent Rittenhouse

De plus, quelqu'un a-t-il une idée pourquoi ← c efface l'écran?! Je ne trouve aucune instance de cela nulle part sur le net. C'est spécifiquement cette combinaison, même si vous semblez également pouvoir avoir des espaces entre les deux personnages. Pour tout autre personnage, il semble juste .. supprimer le premier caractère. Je ne comprends pas ...
Brent Rittenhouse

7

Vous pouvez supprimer la nouvelle ligne en utilisant "tr" de gnuwin32 ( package coreutils )

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

Soit dit en passant, si vous faites beaucoup de scripts, gnuwin32 est une mine d'or.


Je suggère également d' installer git bash . Bien sûr, ce n'est pas la même chose que gnuwin32 (et c'est donc une mine d'or +1), c'est juste une belle configuration, et vous avez git-bash sur le bouton droit de la souris presque partout, y compris le bouton du menu Démarrer.
hakre

pouvez-vous utiliser tr pour supprimer simplement le dernier caractère d'espace, comme dans trim?
panny

utilisez sed pour le trim: sed -e "s / * $ //"
BearCode

@panny - Je ne trouve pas un utilitaire posix / linux appelé trim. En outre, \r, \nou \r\n(nouvelles lignes dans Mac OS X, Posix et Windows respectivement) ne sont pas des caractères « espace ».
user66001

5

Voici une autre méthode, il utilise Powershell Write-Host qui a un paramètre -NoNewLine, combinez-le avec start /bet il offre les mêmes fonctionnalités de lot.

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

Production

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

Celui-ci ci-dessous est légèrement différent, ne fonctionne pas exactement comme le veut l'OP, mais il est intéressant car chaque résultat écrase le résultat précédent en émulant un compteur.

@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

Peut-être que c'est ce que vous cherchez, c'est un script old school ...: 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

ou peut-être essayez-vous de remplacer une ligne actuelle au lieu d'écrire sur une nouvelle ligne? vous pouvez tester cela en supprimant le "% bs%" après le "." signe et également en espaçant les autres "% bs%" après le "Exemple de message".

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

Je trouve cela très intéressant car il utilise une variable dans un autre but que celui pour lequel il est destiné. comme vous pouvez le voir, "% bs%" représente un retour arrière. Le second "% bs%" utilise le retour arrière pour ajouter des espaces après le "Exemple de message" pour séparer la "Sortie de la commande Pause" sans ajouter réellement un caractère visible après le "Exemple de message". Cependant, cela est également possible avec un signe de pourcentage régulier.


2
Je vois cette set nl=^& echo.astuce partout et le nom de la variable est trompeur. % nl% n'est pas un caractère de retour à la ligne : il se développe &echo.donc à la fin vous exécutez une nouvelle echocommande à chaque fois, d'où le retour à la ligne. Vous pouvez le vérifier par écrit echo "%nl%The%nl%new%nl%line%nl%is%nl%not%nl%apparent%nl%throughout%nl%text%nl%". Vous obtenez "& echo. The& echo. new& echo. line& echo. is& echo. not& echo. apparent& echo. throughout& echo. text& echo. ", révélant l'astuce. La sortie est la même mais pas pour les raisons que vous suggérez.
cdlvcdlv

2

cw.exeUtilitaire de bricolage (écriture sur console)

Si vous ne le trouvez pas prêt à l'emploi, prêt à l'emploi, vous pouvez le bricoler. Avec cet cwutilitaire, vous pouvez utiliser tous les types de caractères. J'aimerais au moins le penser. Veuillez faire un test de stress et faites le moi savoir.

Outils

Il vous suffit d' installer .NET , ce qui est très courant de nos jours.

Matériaux

Certains caractères tapés / copiés-collés.

Pas

  1. Créez un .batfichier avec le contenu suivant.
/* >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. Exécuter.

  2. Maintenant, vous avez un bel utilitaire 4Ko afin que vous puissiez supprimer le .bat.

Alternativement, vous pouvez insérer ce code comme sous-programme dans n'importe quel lot, envoyer le résultat .exeà %temp%, l'utiliser dans votre lot et le supprimer lorsque vous avez terminé.

Comment utiliser

Si vous voulez écrire quelque chose sans nouvelle ligne:
cw Whatever you want, even with "", but remember to escape ^|, ^^, ^&, etc. unless double-quoted, like in "| ^ &".

Si vous voulez un retour chariot (aller au début de la ligne), exécutez juste
cw

Essayez donc ceci depuis la ligne de commande:

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

J'ai été inspiré par votre réponse et j'ai créé ce petit outil avec Go et cette tâche d'accompagnement pour Azure Pipelines. Il saisit simplement la sortie standard qui est canalisée et sort celle-ci dans un format spécifique à ramasser par la génération. Je vous remercie!
riezebosch

2

J'ai créé une fonction à partir de l'idée de @arnep:

echo | set / p = "Bonjour tout le monde"

C'est ici:

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

Utilisez-le avec call :SL "Hello There"
je sais que cela n'a rien de spécial mais il m'a fallu si longtemps pour y penser que je pensais que je le posterais ici.


1

Exemple 1: cela fonctionne et produit du code de sortie = 0. C'est bien. Noter la "." , directement après l'écho.

C: \ Users \ phife.dog \ gitrepos \ 1 \ repo_abc \ scripts #
@echo. | set / p JUNK_VAR = Ceci est un message affiché comme Linux echo -n l'afficherait & echo% ERRORLEVEL%

Ceci est un message affiché comme Linux echo -n l'afficherait ... 0

Exemple 2: cela fonctionne mais produit du code de sortie = 1. C'est mauvais. Veuillez noter l'absence de ".", Après l'écho. Cela semble être la différence.

C: \ Users \ phife.dog \ gitrepos \ 1 \ repo_abc \ scripts #
@echo | set / p JUNK_VAR = Ceci est un message affiché comme Linux echo -n l'afficherait & echo% ERRORLEVEL%

Ceci est un message affiché comme Linux echo -n l'afficherait ... 1


1

Inspiré par les réponses à cette question, j'ai créé un script de compteur simple qui continue d'imprimer la valeur de progression (0-100%) sur la même ligne (écrasant la précédente). Peut-être que cela sera également utile à ceux qui recherchent une solution similaire.

Remarque : Les caractères ne *sont pas imprimables, ils doivent être entrés en utilisant la combinaison de touches [ Alt+ Numpad 0+ Numpad 8], qui est le backspacecaractère.

@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

Je crois qu'il n'y a pas une telle option. Vous pouvez également essayer ceci

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

3
Cela imprimera toujours une nouvelle ligne.
René Nyffenegger

3
Vous pouvez concaténer sur la même variable autant que vous le souhaitez et ne faire écho qu'à la toute fin.
m0skit0

2
L'imprimer lors de la boucle ou à la fin n'a pas d'importance si les données sont conservées. Pour chaque boucle, vous concaténez simplement les données, puis lorsque la boucle est terminée, vous l'imprimez. Le résultat est le même.
m0skit0

9
Il n'importe si elle est un indicateur de la progression de la boucle.
gregseth

3
Vous n'avez jamais indiqué cela dans votre question ni demandé ce comportement à aucun endroit de votre question.
m0skit0

0

Vous pouvez supprimer la nouvelle ligne à l'aide de la commande set / p. La commande set / p ne reconnaît pas un espace, pour cela vous pouvez utiliser un point et un caractère de retour arrière pour le faire reconnaître. Vous pouvez également utiliser une variable comme mémoire et y stocker ce que vous souhaitez imprimer, afin de pouvoir imprimer la variable à la place de la phrase. Par exemple:

@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

De cette façon, vous pouvez imprimer n'importe quoi sans nouvelle ligne. J'ai fait le programme pour imprimer les caractères un par un, mais vous pouvez aussi utiliser des mots au lieu de caractères en changeant la boucle.

Dans l'exemple ci-dessus, j'ai utilisé "enabledelayedexpansion" afin que la commande set / p ne reconnaisse pas "!" caractère et imprime un point au lieu de cela. J'espère que vous n'avez pas recours au point d'exclamation "!" ;)


-1

Réponse tardive ici, mais pour toute personne qui a besoin d'écrire des caractères spéciaux sur une seule ligne qui trouve la réponse de dbenham trop longue d'environ 80 lignes et dont les scripts peuvent se casser (peut-être en raison de la saisie de l'utilisateur) sous les limites de la simple utilisation set /p, il est probablement plus facile de simplement associer votre .bat ou .cmd avec un exécutable compilé en C ++ ou en langage C, puis juste coutou printfles caractères. Cela vous permettra également d'écrire facilement plusieurs fois sur une ligne si vous affichez une sorte de barre de progression ou quelque chose utilisant des caractères, comme OP apparemment.


@jiggunjer Vous êtes sûr? printfà partir d'un cmdvolet Win-7 me donne"'printf' is not recognized as an internal or external command, operable program or batch file."
SeldomNeedy

printfn'est pas natif de Windows. Ceci est une question Windows.
kayleeFrye_onDeck

1
@kayleeFrye_onDeck Je suppose que votre commentaire s'adresse à jiggunjer , pas à moi; Je suggère dans ma question que C et C ++ pourraient être utilisés comme une alternative assez indépendante de la plate-forme aux commandes shell dans les cas où le formatage est important.
SeldomNeedy

1
Pardonnez-moi, mon père, car j'ai survolé.
kayleeFrye_onDeck

Mais alors, l'entrée du shell doit être analysée correctement. Par exemple, comment un tel programme imprimerait-il un guillemet?
Alex
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.