Lote do Windows: eco sem nova linha


231

Qual é o equivalente em lote do Windows ao comando shell do Linux echo -nque suprime a nova linha no final da saída?

A idéia é escrever na mesma linha dentro de um loop.



2
isso me fez quase crazy..I sabia echopoderia tomar -n, mas no cmd.exeele simplesmente não iria funcionar ^^
panny

11
@panny - Apesar do nome comum, eco não é o mesmo comando entre o Windows e o Posix. O mesmo que nslookup, possui opções diferentes. Portanto, o comentário "eu sabia que echopoderia levar -n" no contexto de uma pergunta relacionada ao Windows está incorreto.
precisa saber é o seguinte

Respostas:


236

Usando sete o /pparâmetro você pode ecoar sem nova linha:

C:\> echo Hello World
Hello World

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

Fonte


86
O pipe é muito lento, pois cria duas tarefas extras de cmd, mais rápido é <nul set /p =Hello. set /pnão pode ecoar um sinal de igual como primeiro caractere nem espaços / tabulações.
jeb

11
É quase 15 vezes mais rápido no meu sistema
jeb

28
Adicione aspas ao redor de "Hello World" para evitar o espaço estranho após o d.
31712 Brian

13
Aviso: Isso mudará ERRORLEVEL para 1. Consulte a resposta por @xmechanix.
CopiarNick

6
@ user246694 < nulé um redirecionamento do NULdispositivo. Ele contém nada, mas isso é o suficiente para set /pparar de esperar pela entrada do usuário
jeb

100

Usando: echo | set /p=ou <NUL set /p=ambos trabalharão para suprimir a nova linha.

No entanto, isso pode ser muito perigoso ao escrever scripts mais avançados ao verificar ERRORLEVEL se tornar importante, pois a configuração set /p=sem especificar um nome de variável definirá ERRORLEVEL como 1.

Uma abordagem melhor seria usar apenas um nome de variável fictícia da seguinte forma:
echo | set /p dummyName=Hello World

Isso produzirá exatamente o que você deseja, sem que ocorram coisas furtivas em segundo plano, como eu tive que descobrir da maneira mais difícil, mas isso só funciona com a versão canalizada; <NUL set /p dummyName=Helloainda aumentará o ERRORLEVEL para 1.


20
Aviso: Este comando definirá ERRORLEVEL como 0. Se ERRORLEVEL for maior que 0, ele mudará ERRORLEVEL para 0. Isso também pode ser perigoso ao escrever scripts mais avançados. (mas um de resposta)
CoperNick

Então, você basicamente precisa de um IF ERRORLEVEL == 0 (...) ELSE (...) apenas para não prejudicar seu ambiente nessas circunstâncias. Sheesh.
SilverbackNet

28

O método SET / P simples tem limitações que variam um pouco entre as versões do Windows.

  • As cotações principais podem ser removidas

  • Os espaços em branco à esquerda podem ser removidos

  • Leading =causa um erro de sintaxe.

Consulte http://www.dostips.com/forum/viewtopic.php?f=3&t=4209 para obter mais informações.

jeb postou uma solução inteligente que resolve a maioria dos problemas no texto Saída sem avanço de linha, mesmo com espaço à esquerda ou = Refinei o método para que ele possa imprimir com segurança absolutamente qualquer sequência de lotes válida sem a nova linha, em qualquer versão do Windows do XP em diante. Observe que o :writeInitializemétodo contém uma literal de seqüência de caracteres que pode não ser boa para o site. É incluída uma observação que descreve qual deve ser a sequência de caracteres.

Os métodos :writee :writeVarsão otimizados de forma que somente as seqüências contendo caracteres iniciais problemáticos sejam gravadas usando minha versão modificada do método COPY da jeb. Strings não problemáticas são gravadas usando o método SET / P mais simples e rápido.

@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
Bom ver uma solução muito poderosa que pode lidar com todos os personagens
jeb

2
Gostaria de ressaltar que, se o computador tiver uma conexão de rede com a Internet, esse código de lote pode ser usado para baixar e instalar o python ou qualquer outra coisa no computador que possa livrar você do lote. Lote é divertido, no entanto, seus recursos de cordas são melhores para o desafio do fim de semana.
N611x007 9/07

@dbenham na linha 6 "echo (" é funcionalmente o mesmo que "echo". - não tinha visto isso antes.
Skip R

2
@ SkipR - Sim, é funcionalmente o mesmo que ECHO., exceto que ECHO.pode falhar em circunstâncias obscuras . Existem várias outras formas que também podem falhar em situações obscuras. O único que sempre funciona é ECHO(.
dbenham

10

Como um adendo à resposta do @ xmechanix, notei escrevendo o conteúdo em um arquivo:

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

Isso adicionará um espaço extra ao final da string impressa , o que pode ser inconveniente, especialmente porque estamos tentando evitar adicionar uma nova linha (outro caractere de espaço em branco) ao final da string.

Felizmente, citando a string a ser impressa, ou seja, usando:

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

Irá imprimir a sequência sem nenhum caractere de nova linha ou espaço no final.


5
O espaço extra deve desaparecer se você não colocar um espaço entre Worlde >...
aschipfl

@aschipfl Tentei, não.
Joan Bruguera

A variável Quoted Method, um recurso não documentado do comando set, geralmente é como vejo que deve ser abordada, pois funciona em todas as versões do Windows NT (e 9x, se bem me lembro). Ou seja, você coloca o nome da variável no final do valor entre aspas. Isso também é válido para Set / P.
precisa

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

2
@aschipfl Um espaço extra aparecerá se você não fizer aspas e fizer um cachimbo. xxd é um utilitário de despejo hex assim vemos por exemplo, set /p="abc"<nul|xxd -pexibe 616263 enquanto set /p=abc<nul|xxd -p61626320
barlop

9

Uma solução para o espaço em branco despojado em SET / P:

o truque é o char de backspace que você pode chamar no editor de texto EDIT for DOS. Para criá-lo em EDIT, pressione ctrlP + ctrlH . Gostaria de colá-lo aqui, mas esta página não pode exibi-lo. No entanto, é visível no bloco de notas (era vazio, como um pequeno retângulo preto com um círculo branco no centro)

Então você escreve isso:

<nul set /p=.9    Hello everyone

O ponto pode ser qualquer caractere, é só para informar ao SET / P que o texto começa ali, antes dos espaços, e não no " Hello ". O " 9 " é uma representação do caractere de backspace que não posso exibir aqui. Você deve colocá-lo no lugar do 9 e ele excluirá o " . ", Após o qual você obterá o seguinte:

    Hello Everyone

ao invés de:

Hello Everyone

Espero que ajude


2
Esqueci de dizer que funciona no Windows 7. Não funciona em uma linha de comando, apenas em um lote. Para quem não está recebendo o char, faça o download deste exemplo: pecm.com.sapo.pt/SET_with_backspace_char.txt
Pedro

Também é verdade for Echo
Ben Personick

... Então, depois de fazer uma pesquisa minuciosa, ainda não encontrei isso em nenhum lugar da Internet. Pode ser a única vez que eu realmente descobri algo, e por pura sorte. Para quem não sabe, você PODE inserir caracteres de controle se colocar o prompt do cmd no modo legado e usar a fonte correta. ... Mas se você simplesmente redirecionar qualquer coisa para um arquivo ou> con, também funcionará. Seriamente. Cole EXATAMENTE isso no seu prompt de comando: "eco ← c◙◙ ○○ Harharhar !! ◙ ○○ ------------- ◙◙ ○○ Eu sou o pior!?: '(○ ♪ ○ NOPE! • ♪ ○ Eu me sinto ótimo! Hazzah-le-oop! ◙◙ Eu sou programador, me ouça ... alguma coisa.◙> con ".
Brent Rittenhouse

Ok, espero ter descoberto isso antes de mais alguém, mas ... isso parece depender de não estar em uma página de código unicode. Você pode armazenar o inicial em uma variável do chcp 437, definir o conjunto em uma variável ou produzi-la e depois retornar (e ainda deve produzir). Ainda estou brincando com isso.
Brent Rittenhouse

Além disso, alguém tem alguma idéia do porquê ← c limpa a tela ?! Não consigo encontrar uma instância disso em nenhum lugar da rede. É especificamente essa combinação, embora você pareça ter espaço em branco entre os dois caracteres também. Para qualquer outro personagem, parece apenas remover o primeiro caractere. Eu não entendo ...
Brent Rittenhouse

7

Você pode remover a nova linha usando "tr" do gnuwin32 ( pacote coreutils )

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

A propósito, se você estiver executando muitos scripts, o gnuwin32 é uma mina de ouro.


Eu também sugiro instalar o git bash . Certifique-se de que não é o mesmo que gnuwin32 (e é uma mina de ouro, portanto, +1), é apenas uma boa configuração e você tem o git-bash com o botão direito do mouse em quase todos os lugares, incluindo o botão do menu iniciar.
hakre

você pode usar tr para remover o último caractere de espaço, como em trim?
panny

use sed para trim: sed -e "s / * $ //"
BearCode 5/13/13

@panny - Não consigo encontrar um utilitário posix / linux chamado trim. Além disso, \r, \nou \r\n(Novas linhas em OSX, POSIX e Windows, respectivamente) não são "espaço" caracteres.
user66001

5

Aqui está outro método: ele usa o Powershell Write-Host que possui um parâmetro -NoNewLine, combina isso com start /be oferece a mesma funcionalidade do lote.

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

Resultado

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

Este abaixo é um pouco diferente, não funciona exatamente como o OP deseja, mas é interessante porque cada resultado substitui o resultado anterior emulando um contador.

@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

Talvez seja isso que você está procurando, é um roteiro da velha escola ...: 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 talvez você esteja tentando substituir uma linha atual em vez de gravar em uma nova linha? você pode experimentar isso removendo o "% bs%" após o "." assinar e também espaçando os outros "% bs%" após a "mensagem de exemplo".

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

Acho isso realmente interessante porque usa uma variável para um propósito diferente do que se destina a fazer. como você pode ver, o "% bs%" representa um backspace. O segundo "% bs%" usa o backspace para adicionar espaços após a "mensagem de exemplo" para separar a "saída do comando Pause" sem realmente adicionar um caractere visível após a "mensagem de exemplo". No entanto, isso também é possível com um sinal de porcentagem regular.


2
Eu vejo esse set nl=^& echo.truque em todos os lugares e o nome da variável é enganoso. % nl% não é um caractere de nova linha : ele se expande para &echo.que, no final, você execute um novo echocomando toda vez, daí a nova linha. Você pode conferir por escrito echo "%nl%The%nl%new%nl%line%nl%is%nl%not%nl%apparent%nl%throughout%nl%text%nl%". Você consegue "& echo. The& echo. new& echo. line& echo. is& echo. not& echo. apparent& echo. throughout& echo. text& echo. ", revelando o truque. A saída é a mesma, mas não pelos motivos sugeridos.
Cdlvcdlv

2

cw.exeUtilitário DIY (gravação no console)

Se você não o encontrar pronto para o uso, pronto para uso, faça você mesmo. Com este cwutilitário, você pode usar todos os tipos de caracteres. Pelo menos, gostaria de pensar que sim. Faça um teste de estresse e me avise.

Ferramentas

Tudo que você precisa é .NET instalado, o que é muito comum atualmente.

Materiais

Alguns caracteres digitados / copiados e colados.

Passos

  1. Crie um .batarquivo com o seguinte conteúdo.
/* >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. Executá-lo.

  2. Agora você tem um bom utilitário de 4KB para excluir o arquivo .bat.

Alternativamente, você pode inserir este código como uma sub-rotina em qualquer lote, enviar o resultado .exepara %temp%, usá-lo em seu lote e excluí-lo quando estiver pronto.

Como usar

Se você quiser escrever algo sem nova linha:
cw Whatever you want, even with "", but remember to escape ^|, ^^, ^&, etc. unless double-quoted, like in "| ^ &".

Se você deseja um retorno de carro (indo para o início da linha), execute apenas
cw

Então, tente isso na linha de comando:

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

Fiquei inspirado pela sua resposta e criei esta pequena ferramenta com o Go e esta tarefa que acompanha os Pipelines do Azure. Ele apenas pega o stdout que é inserido e o gera em um formato específico para ser capturado pela compilação. Obrigado!
riezebosch

2

Eu criei uma função com a idéia de @arnep:

eco | set / p = "Olá, mundo"

Aqui está:

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

Use-o com call :SL "Hello There"
Eu sei que isso não é nada de especial, mas demorei tanto tempo para pensar sobre isso, e pensei em publicá-lo aqui.


1

Exemplo 1: Isso funciona e produz o código de saída = 0. Isso é bom. Note o "." , diretamente após o eco.

C: \ Usuários \ phife.dog \ gitrepos \ 1 \ repo_abc \ scripts #
@echo. set / p JUNK_VAR = Esta é uma mensagem exibida como Linux echo -n exibirá ... & echo% ERRORLEVEL%

Esta é uma mensagem exibida como Linux echo -n a exibirá ... 0

Exemplo 2: Isso funciona, mas produz o código de saída = 1. Isso é ruim. Observe a falta de ".", Após o eco. Essa parece ser a diferença.

C: \ Usuários \ phife.dog \ gitrepos \ 1 \ repo_abc \ scripts #
@echo | set / p JUNK_VAR = Esta é uma mensagem exibida como Linux echo -n exibirá ... & echo% ERRORLEVEL%

Esta é uma mensagem exibida como Linux echo -n mostraria ... 1


1

Inspirado nas respostas a essa pergunta, criei um script simples de contra-lote que continua imprimindo o valor do progresso (0-100%) na mesma linha (substituindo o anterior). Talvez isso também seja valioso para quem procura uma solução semelhante.

Observação : *os caracteres não são imprimíveis e devem ser inseridos usando a combinação de teclas [ Alt+ Numpad 0+ Numpad 8], que é o backspacecaractere.

@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

Eu acredito que não existe essa opção. Como alternativa, você pode tentar isso

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

3
Isso ainda imprimirá uma nova linha.
René Nyffenegger 18/08/11

3
Você pode concatenar na mesma variável o quanto quiser e apenas ecoar no final.
precisa saber é o seguinte

2
Imprimi-lo ao fazer o loop ou no final não importa se os dados são preservados. Para cada loop, basta concatenar os dados e, quando o loop terminar, você os imprime. O resultado é o mesmo.
M0skit0

9
Ele não importa se é um indicador da progressão do ciclo.
gregseth

3
Você nunca declarou isso na sua pergunta ou solicitou esse comportamento em qualquer lugar da sua pergunta.
M0skit0

0

Você pode suprimir a nova linha usando o comando set / p. O comando set / p não reconhece um espaço, para isso você pode usar um ponto e um caractere de backspace para fazê-lo reconhecê-lo. Você também pode usar uma variável como memória e armazenar o que deseja imprimir nela, para poder imprimir a variável em vez da frase. Por exemplo:

@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

Dessa forma, você pode imprimir qualquer coisa sem uma nova linha. Eu criei o programa para imprimir os caracteres um por um, mas você também pode usar palavras em vez de caracteres alterando o loop.

No exemplo acima, usei "enabledelayedexpansion" para que o comando set / p não reconheça "!" caractere e imprime um ponto em vez disso. Espero que você não tenha o uso do ponto de exclamação "!" ;)


-1

Resposta tardia aqui, mas para quem precisar escrever caracteres especiais em uma única linha que ache a resposta do dbenham com cerca de 80 linhas demais e cujos scripts possam ser interrompidos (talvez devido à entrada do usuário) sob as limitações de simplesmente usar set /p, é provavelmente mais fácil apenas para emparelhar o .bat ou .cmd com um compilado C ++ ou executável em linguagem C e depois é só coutou printfos personagens. Isso também permitirá que você escreva facilmente várias vezes em uma linha se estiver mostrando uma espécie de barra de progresso ou algo usando caracteres, como aparentemente o OP.


@jiggunjer Você tem certeza? printfA partir de um cmdpainel Win-7, dá-me "'printf' is not recognized as an internal or external command, operable program or batch file."
#

printfnão é nativo do Windows. Esta é uma pergunta do Windows.
precisa saber é o seguinte

1
@kayleeFrye_onDeck Presumo que seu comentário seja direcionado a jiggunjer , não a mim; Sugiro na minha pergunta que C e C ++ possam ser usados ​​como uma alternativa bastante independente da plataforma aos comandos do shell nos casos em que a formatação é importante.
SeldomNeedy 29/09/16

1
Perdoe-me pai, porque eu desnatado.
precisa saber é o seguinte

Mas então a entrada para o shell precisa ser analisada corretamente. Por exemplo, como esse programa imprimiria aspas?
22417 Alex
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.