web-dev-qa-db-fra.com

Lot Windows: echo sans nouvelle ligne

Quel est l'équivalent Batch Windows de la commande Linux Shell echo -n qui 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.

188
gregseth

En utilisant set et le paramètre /p, vous pouvez effectuer un écho sans nouvelle ligne:

C:\> echo Hello World
Hello World

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

La source

197
arnep

Utiliser: echo | set /p= ou <NUL set /p= permettra à la fois de supprimer la nouvelle ligne.

Cependant, cela peut s'avérer très dangereux lorsque vous écrivez des scripts plus avancés, car vérifier qu'ERRORLEVEL devient important, car définir set /p= sans spécifier de nom de variable définit ERRORLEVEL sur 1.

Une meilleure approche consisterait simplement à utiliser un nom de variable factice, comme ceci:
echo | set /p dummyName=Hello World 

Cela produira exactement ce que vous voulez sans qu'il y ait de trucs sournois à l'arrière-plan, car je devais trouver la méthode la plus difficile, mais cela ne fonctionne qu'avec la version Pipe; <NUL set /p dummyName=Hello va toujours élever ERRORLEVEL à 1.

85
xmechanix

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

  • Les guillemets peuvent être supprimés

  • Un espace blanc de premier plan peut être dépouillé

  • L'interligne = provoque 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 Sortie de texte sans saut de ligne, même avec un espace de début ou = J'ai raffiné la méthode pour pouvoir imprimer en toute sécurité toute chaîne de lot valide sans la nouvelle ligne toute version de Windows à partir de XP. Notez que la méthode :writeInitialize contient un littéral qui pourrait ne pas être bien publié sur le site. Une remarque est incluse qui décrit ce que la séquence de caractères devrait être.

Les méthodes :write et :writeVar sont optimisées de sorte que seules les chaînes contenant des caractères de tête gênants sont écrites à l'aide de la 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
25
dbenham

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

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

Alors vous écrivez ceci:

<nul set /p=.9    Hello everyone

Le point peut être n’importe quel caractère, c’est uniquement là pour indiquer à SET/P que le texte commence par celui-ci, avant les espaces, et non au "_ ​​Hello" . 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

9
Pedro

En tant qu'additif à 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 que nous essayons d'éviter d'ajouter une nouvelle ligne (un autre caractère d'espacement) à la fin de la chaîne.

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

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

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

8
Joan Bruguera

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

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

À propos, si vous utilisez beaucoup de scripts, gnuwin32 est une mine d’or.

7
BearCode

Voici une autre méthode, elle utilise Powershell Write-Host qui a un paramètre -NoNewLine, combine cela avec start /b et offre les mêmes fonctionnalités que 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

Sortie

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

Celui ci-dessous est légèrement différent, ne fonctionne pas exactement comme le veut le PO, 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
5
Knuckle-Dragger

De ici

<nul set /p =Testing testing

et aussi pour faire écho en commençant par utiliser des espaces

echo.Message goes here

DIY cw.exe (écriture de la console)

Si vous ne le trouvez pas prêt à l'emploi, vous pouvez le faire vous-même. Avec cet utilitaire cw, vous pouvez utiliser tous les types de caractères. Au moins, j'aimerais bien le penser. S'il vous plaît stress-test et faites le moi savoir.

Outils

Tout ce dont vous avez besoin est .NET installed, ce qui est très courant actuellement.

Matériaux

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

Pas

  1. Créez un fichier .bat 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 utilitaire Nice 4KB afin que vous puissiez supprimer le .bat.

Vous pouvez également insérer ce code en tant que sous-routine dans n’importe quel lot, envoyer le .exe résultant à %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), lancez simplement
cw

Alors essayez ceci depuis la ligne de commande:

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

C’est peut-être ce que vous cherchez, c’est un vieux script d’école ...: 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 que vous essayez de remplacer une ligne en cours au lieu d’écrire sur une nouvelle ligne? Vous pouvez essayer cela en supprimant le "% bs%" après le "." et en espaçant l'autre "% bs%" après le "message d'exemple".

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 but autre que celui auquel elle est destinée. comme vous pouvez le voir, "% bs%" représente un retour arrière. Le second "% bs%" utilise l'espace arrière pour ajouter des espaces après le "message exemple" afin de séparer la "sortie de la commande de pause" sans ajouter de caractère visible après le "message exemple". Cependant, cela est également possible avec un signe de pourcentage régulier. 

2
zask

Exemple 1: Cela fonctionne et produit le code de sortie = 0. C'est bon. Noter la "." , directement après écho.

C:\Utilisateurs\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 le ferait apparaître ... 0

Exemple 2: Cela fonctionne mais produit un code de sortie = 1. C'est mauvais. S'il vous plaît noter le manque de ".", Après l'écho. Cela semble être la différence.

C:\Utilisateurs\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 voudrait l'afficher ... 1 

1
user3175529

Réponse tardive ici, mais pour tous ceux qui ont besoin d'écrire des caractères spéciaux sur une seule ligne et qui trouvent que la réponse de dbenham est trop longue de 80 lignes et dont les scripts risquent de se briser (peut-être à cause des entrées de l'utilisateur) dans les limites En utilisant simplement set /p, il est probablement plus facile de simplement associer votre .bat ou .cmd à un exécutable compilé en C++ ou en langage C, puis simplement à cout ou printf les caractères. Cela vous permettra également d’écrire facilement plusieurs fois sur une seule ligne si vous affichez une sorte de barre de progression ou quelque chose utilisant des caractères, comme l’a été apparemment OP.

0
SeldomNeedy

Je crois qu'il n'y a pas une telle option. Sinon, vous pouvez essayer cela

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

Vous pouvez supprimer la nouvelle ligne à l'aide de la commande set/p. La commande set/p ne reconnaît pas d'espace, vous pouvez donc 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 voulez imprimer, de manière à 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 créé le programme pour imprimer les caractères un par un, mais vous pouvez aussi utiliser des mots au lieu de caractères en modifiant 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 l'utilisation du point d'exclamation "!" ;)

J'ai créé l'idée de @arnep: 

echo | set/p = "Hello World" 

C'est ici:

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

Utilisez-le avec call :SL "Hello There"
Je sais que ce n’est pas spécial, mais j’ai mis si longtemps à y penser que j’ai pensé le poster ici.

0
Mark Deven