Пакет Windows: эхо без новой строки

231

Что такое пакетный эквивалент Windows для команды оболочки Linux, echo -nкоторая подавляет символ новой строки в конце вывода?

Идея состоит в том, чтобы писать в одной строке внутри цикла.

gregseth
источник
2
это привело меня в бешенство .. Я знал, что echoможет взять, -nно cmd.exeэто просто не сработает ^^
Панни
11
@panny - Несмотря на общее название, echo - это не одна и та же команда между Windows и Posix. Так же, как nslookup, у него есть разные варианты. Таким образом, комментарий «Я знал, что echoмог взять -n» в контексте вопроса, связанного с Windows, является неправильным.
user66001

Ответы:

236

Используя setи /pпараметр, вы можете отображать без новой строки:

C:\> echo Hello World
Hello World

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

Источник

arnep
источник
86
Канал очень медленный, поскольку создает две дополнительные cmd-задачи, быстрее <nul set /p =Hello. set /pне может отображать знак равенства как первый символ, так и пробелы / символы табуляции.
Джеб
11
Это почти в 15 раз быстрее в моей системе
Джеб
28
Добавьте кавычки вокруг "Hello World", чтобы избежать постороннего пробела после d.
Брайан
13
Предупреждение: это изменит ERRORLEVEL на 1. См. Ответ @xmechanix.
CoperNick
6
@ user246694 < nul- это перенаправление с NULустройства. Он не содержит ничего, но этого достаточно, set /pчтобы перестать ждать ввода пользователя
Джеб
100

Использование: echo | set /p=или <NUL set /p=оба будут работать для подавления новой строки.

Однако это может быть очень опасно, когда написание более сложных сценариев, когда проверка ERRORLEVEL становится важной, так как установка set /p=без указания имени переменной установит для ERRORLEVEL значение 1.

Лучшим подходом было бы просто использовать фиктивное имя переменной следующим образом:
echo | set /p dummyName=Hello World

Это произведет именно то, что вы хотите, без каких-либо подлых вещей, происходящих в фоновом режиме, так как мне пришлось выяснить трудный путь, но это работает только с конвейерной версией; <NUL set /p dummyName=Helloвсе равно поднимет ОШИБКУ до 1.

xmechanix
источник
20
Предупреждение: эта команда установит для ERRORLEVEL значение 0. Если значение ERRORLEVEL было больше 0, оно изменит значение ERRORLEVEL на 0. Это также может быть опасно при написании более сложных сценариев. (но +1 за ответ)
CoperNick
Таким образом, вам в основном нужен IF ERRORLEVEL == 0 (...) ELSE (...), чтобы не нанести вред вашей среде в этих обстоятельствах. Sheesh.
SilverbackNet
28

Простой метод SET / P имеет ограничения, которые немного различаются в разных версиях Windows.

  • Ведущие цитаты могут быть удалены

  • Ведущие пробелы могут быть удалены

  • Ведущий =вызывает синтаксическую ошибку.

См. Http://www.dostips.com/forum/viewtopic.php?f=3&t=4209 для получения дополнительной информации.

Джеб опубликовал умное решение, которое решает большинство проблем в тексте вывода без перевода строки, даже с начальным пробелом или = я усовершенствовал метод, чтобы он мог безопасно печатать абсолютно любую допустимую строку пакета без новой строки в любой версии Windows от XP и далее. Обратите внимание, что :writeInitializeметод содержит строковый литерал, который может плохо размещаться на сайте. Включено примечание, описывающее, какой должна быть последовательность символов.

:writeИ :writeVarметоды оптимизированы таким образом, что только строки , содержащие хлопотно ведущие символы записываются с помощью моей модифицированной версии метода COPY Джеба. Беспроблемные строки пишутся с использованием более простого и быстрого метода SET / P.

@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
dbenham
источник
1
Приятно видеть очень мощное решение, которое может обрабатывать все персонажи
Джеб
2
Я хотел бы отметить, что, если у компьютера есть сетевое подключение к Интернету, примерно столько же пакетного кода может быть использовано для загрузки и установки на компьютер python или чего-либо еще, что поможет вам избавиться от пакета. Пакетная игра - это весело, но ее возможности струн лучше всего подходят для выходных.
n611x007
@dbenham в строке 6 "echo (") - это то же самое, что и "echo." - такого раньше не было.
Пропустить R
2
@SkipR - Да, это функционально так же, как ECHO., за исключением, ECHO.может потерпеть неудачу при неизвестных обстоятельствах . Есть множество других форм, которые также могут потерпеть неудачу в непонятных ситуациях. Единственное, что всегда работает, это ECHO(.
ДБЕНХАМ
10

В качестве дополнения к ответу @ xmechanix я заметил, записав содержимое в файл:

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

Это добавит дополнительный пробел в конце напечатанной строки , что может быть неудобно, особенно если учесть, что мы пытаемся избежать добавления новой строки (другого символа пробела) в конец строки.

К счастью, цитирование строки для печати, то есть с помощью:

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

Напечатает строку без символа перевода строки или пробела в конце.

Джоан Бругера
источник
5
Дополнительный пробел должен исчезнуть, если вы не поставите пробел между Worldи >...
aschipfl
@aschipfl попробовал, это не так.
Джоан Бругера
Метод переменных в кавычках, недокументированная особенность команды set, - это, как я понимаю, подход к нему, так как он работает во всех версиях Windows NT (и 9x, если я помню). То есть вы заключаете имя переменной в конец значения в кавычках. Это верно и для Set / P.
Бен
1
IE: эхо | set / p "dummyName = Hello World"> somefile.txt
Бен
2
@aschipfl Дополнительный пробел появится, если вы не делаете кавычки, а вы делаете трубу. xxd - это утилита шестнадцатеричного дампа, поэтому мы видим, например, set /p="abc"<nul|xxd -pотображает, 616263 тогда как set /p=abc<nul|xxd -pдает61626320
barlop
9

Решение для очищенного белого пространства в SET / P:

хитрость заключается в том символе возврата, который вы можете вызвать в текстовом редакторе EDIT для DOS. Чтобы создать его в режиме EDIT, нажмите Ctrl + CtrlH . Я вставил бы это здесь, но эта веб-страница не может отобразить это. Хотя он виден в блокноте (он странный, как маленький черный прямоугольник с белым кружком в центре)

Итак, вы пишете это:

<nul set /p=.9    Hello everyone

Точка может быть любым символом, это только там, чтобы сказать SET / P, что текст начинается там, перед пробелами, а не в " Hello ». « 9 » - это представление символа возврата, которое я не могу отобразить здесь. Вы должны поставить его вместо 9, и он удалит « . », После чего вы получите это:

    Hello Everyone

вместо того:

Hello Everyone

Я надеюсь, что это помогает

Pedro
источник
2
Я забыл сказать, что это работает в Windows 7. Это не будет работать в командной строке, только в пакетном режиме. Для тех, кто не получает чар, скачайте этот пример: pecm.com.sapo.pt/SET_with_backspace_char.txt
Педро
Также верно для Эха
Бен
... Итак, после довольно тщательного поиска я НИКОГДА не нашел этого в сети. Это может быть один раз, когда я действительно что-то обнаружил, и по счастливой случайности. Для тех, кто не знает, МОЖЕТ вводить управляющие символы, если вы переводите приглашение cmd в устаревший режим и используете правильный шрифт. ... Но если вы просто перенаправляете что-либо в файл или> con, это тоже работает. Шутки в сторону. Вставьте это ТОЧНО в командную строку: "echo ← c◙◙ ○○ Harharhar !! ◙ ○○ ------------- ◙◙ ○○ Я худший!?: '(○ ♪ ○ NOPE! • ♪ ○ Я прекрасно себя чувствую! Хазз-ле-ооп! ○ ○ Я программист, услышь меня ... что-то.
Брент Риттенхаус
Хорошо, я надеюсь, что узнал об этом раньше всех, но ... это, похоже, зависит от отсутствия в кодовой странице Unicode. Вы можете сохранить начальную переменную в do chcp 437, установить набор в переменную или вывести ее, а затем переключиться обратно (и она все равно должна выводиться). Я все еще играю с этим.
Брент Риттенхаус
Кроме того, кто-нибудь имеет представление, почему ← c очищает экран ?! Я не могу найти экземпляр этого нигде в сети. Это именно такая комбинация, хотя вы, кажется, также можете иметь пробел между двумя символами. Для любого другого персонажа это просто ... удалить первый символ. Я не понимаю ...
Брент Риттенхаус
7

Вы можете удалить новую строку, используя "tr" из gnuwin32 ( пакет coreutils )

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

Кстати, если вы делаете много сценариев, gnuwin32 - это золотая жила.

BearCode
источник
Я также предлагаю установить git bash . конечно, это не то же самое, что gnuwin32 (и это золотая жила, следовательно, +1), это просто хорошая настройка, и у вас есть git-bash на правой кнопке мыши почти везде, включая кнопку меню пуск.
Хакре
Вы можете использовать tr, чтобы просто удалить последний пробел, как в trim?
Панни
используйте sed для отделки: sed -e "s / * $ //"
BearCode
@panny - я не могу найти утилиту posix / linux под названием trim. Кроме того , \r, \nили \r\n(новые строки в OSX, Posix и Windows , соответственно) не являются «космическими» символами.
user66001
5

Вот еще один метод, он использует Powershell Write-Host, у которого есть параметр -NoNewLine, объедините его с start /b и предлагает те же функциональные возможности из пакета.

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

Вывод

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

Это ниже немного отличается, не работает точно так, как хочет OP, но интересно, потому что каждый результат перезаписывает предыдущий результат, эмулирующий счетчик.

@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
Knuckle-Dragger
источник
3

От сюда

<nul set /p =Testing testing

а также повторить, начиная с использования пробелов

echo.Message goes here
Afdsafnadsjbcewjhwnfy4ntc874fg
источник
2

Может быть, это то, что вы ищете, это сценарий старой школы ...: 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

или, может быть, вы пытаетесь заменить текущую строку вместо записи в новую строку? Вы можете поэкспериментировать с этим, удалив «% bs%» после «.» знак, а также через интервал между "% bs%" после "Пример сообщения".

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

Я нахожу это действительно интересным, потому что он использует переменную не для той цели, для которой он предназначен. как вы можете видеть, "% bs%" представляет собой забой. Второй «% bs%» использует пробел для добавления пробелов после «Пример сообщения» для разделения «Вывод команды Пауза» без фактического добавления видимого символа после «Пример сообщения». Однако это также возможно с обычным знаком процента.

Zask
источник
2
Я вижу этот set nl=^& echo.трюк везде, и имя переменной вводит в заблуждение. % п% есть не новой строки символов : она расширяется &echo.так , в конце концов вы работаете новую echoкоманду каждый раз, следовательно , символ новой строки. Вы можете проверить это в письменной форме echo "%nl%The%nl%new%nl%line%nl%is%nl%not%nl%apparent%nl%throughout%nl%text%nl%". Вы получаете "& echo. The& echo. new& echo. line& echo. is& echo. not& echo. apparent& echo. throughout& echo. text& echo. ", раскрывая трюк. Вывод такой же, но не по тем причинам, которые вы предлагаете.
cdlvcdlv
2

DIY cw.exe (консольная запись) утилита

Если вы не найдете его готовым, готовым, вы можете сделать это самостоятельно. С этимcw утилиты вы можете использовать любые символы. По крайней мере, мне бы хотелось так думать. Пожалуйста, стресс-тест и дайте мне знать.

инструменты

Все, что вам нужно, это установить .NET , что очень распространено в наши дни.

материалы

Некоторые символы напечатаны / скопированы.

меры

  1. Создайте .batфайл со следующим содержанием.
/* >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. Запустить его.

  2. Теперь у вас есть хорошая утилита 4KB, поэтому вы можете удалить .bat.

Кроме того , вы можете вставить этот код в качестве подпрограммы в любой партии, отправить в результате .exeк %temp%, использовать его в своей партии и удалить его , когда вы закончите.

Как пользоваться

Если вы хотите написать что-то без новой строки:
cw Whatever you want, even with "", but remember to escape ^|, ^^, ^&, etc. unless double-quoted, like in "| ^ &".

Если вы хотите возврат каретки (переход к началу строки), просто запустите
cw

Так что попробуйте это из командной строки:

for /l %a in (1,1,1000) do @(cw ^|&cw&cw /&cw&cw -&cw&cw \&cw)
cdlvcdlv
источник
Я был вдохновлен вашим ответ и создал этот маленький инструмент с Go и это сопутствующая задачей Azure трубопроводов. Он просто получает стандартный вывод и выводит его в определенном формате, который будет выбран сборкой. Спасибо!
riezebosch
2

Я сделал функцию из идеи @arnep:

echo | set / p = "Hello World"

вот:

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

Используйте это с, call :SL "Hello There"
я знаю, что в этом нет ничего особенного, но я так долго думал об этом, что я решил опубликовать это здесь.

Марк Девен
источник
1

Пример 1: Это работает и производит код выхода = 0. Это хорошо. Обратите внимание "." сразу после эха.

C: \ Users \ phife.dog \ gitrepos \ 1 \ repo_abc \ scripts #
@echo. | set / p JUNK_VAR = Это сообщение отображается как Linux echo -n будет отображать его ... & echo% ERRORLEVEL%

Это сообщение отображается как Linux echo -n будет отображать его ... 0

Пример 2: это работает, но выдает код выхода = 1. Это плохо. Обратите внимание на отсутствие "." После эха. Похоже, что это разница.

C: \ Users \ phife.dog \ gitrepos \ 1 \ repo_abc \ scripts #
@echo | set / p JUNK_VAR = Это сообщение отображается как Linux echo -n будет отображать его ... & echo% ERRORLEVEL%

Это сообщение отображается как Linux эхо -n будет отображать его ... 1

user3175529
источник
1

Вдохновленный ответами на этот вопрос, я сделал простой пакетный скрипт счетчика, который продолжает печатать значение прогресса (0-100%) в той же строке (перезаписывая предыдущий). Возможно, это также будет полезно для других, ищущих подобное решение.

Примечание : *это непечатаемые символы, их следует вводить с помощью комбинации клавиш [ Alt+ Numpad 0+ Numpad 8], которая является backspaceсимволом.

@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
Spinicoffee
источник
0

Я считаю, что нет такой возможности. Или вы можете попробовать это

set text=Hello
set text=%text% world
echo %text%
m0skit0
источник
3
Это все еще напечатает новую строку.
Рене Ниффенеггер
3
Вы можете объединить одну и ту же переменную сколько хотите, и только эхо в самом конце.
m0skit0
2
Печать его при выполнении цикла или в конце не имеет значения, сохранятся ли данные. Для каждого цикла вы просто объединяете данные, а затем, когда цикл заканчивается, вы печатаете его. Результат тот же.
m0skit0
9
Не имеет значения, является ли это индикатором развития цикла.
Gregseth
3
Вы никогда не заявляли об этом в своем вопросе и не запрашивали такого поведения нигде в своем вопросе.
m0skit0
0

Вы можете подавить новую строку, используя команду set / p. Команда set / p не распознает пробел, для этого вы можете использовать точку и символ возврата, чтобы она его распознала. Вы также можете использовать переменную в качестве памяти и сохранить то, что вы хотите напечатать в ней, чтобы вы могли напечатать переменную вместо предложения. Например:

@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

Таким образом, вы можете напечатать что-нибудь без новой строки. Я сделал программу для печати символов один за другим, но вы также можете использовать слова вместо символов, изменив цикл.

В приведенном выше примере я использовал «enabledelayedexpansion», поэтому команда set / p не распознает «!» символ и печатает точку вместо этого. Я надеюсь, что вы не используете восклицательный знак "!" ;)

Дж. Рагхава Рама Шарма
источник
-1

Поздний ответ здесь, но для тех, кому нужно написать специальные символы в одной строке, для которых ответ dbenham слишком длинный, примерно на 80 строк и чьи сценарии могут ломаться (возможно, из-за ввода данных пользователем) из-за ограничений простого использования set /p, вероятно, проще всего связать ваш .bat или .cmd с скомпилированным исполняемым файлом на C ++ или языке C, а затем просто coutили printfс символами. Это также позволит вам легко писать несколько раз в одну строку, если вы показываете какой-то индикатор выполнения или что-то с использованием символов, как, очевидно, было в OP.

SeldomNeedy
источник
@jiggunjer Ты уверен? printfс cmdпанели Win-7 дает мне"'printf' is not recognized as an internal or external command, operable program or batch file."
SeldomNeedy
printfне является родным для Windows. Это вопрос Windows.
kayleeFrye_onDeck
1
@kayleeFrye_onDeck Я предполагаю, что ваш комментарий направлен на jiggunjer , а не на меня; В моем вопросе я предлагаю использовать C и C ++ в качестве довольно независимой от платформы альтернативы командам оболочки в тех случаях, когда форматирование важно.
SeldomNeedy
1
Прости меня, отец, потому что я снялся.
kayleeFrye_onDeck
Но тогда вход в оболочку должен быть правильно проанализирован. Например, как такая программа будет печатать кавычку?
Алекс