Пакет Windows: эхо без новой строки - PullRequest
200 голосов
/ 18 августа 2011

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

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

Ответы [ 15 ]

210 голосов
/ 18 августа 2011

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

C:\> echo Hello World
Hello World

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

Источник

91 голосов
/ 05 июля 2012

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

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

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

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

26 голосов
/ 19 октября 2013

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

  • Могут быть удалены ведущие кавычки

  • Пробел в началеможет быть удален

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

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

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

Методы :write и :writeVar оптимизированы таким образом, что только строки, содержащие проблемные начальные символы, пишутся с использованием моей модифицированной версии метода jeb 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
10 голосов
/ 05 февраля 2016

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

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

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

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

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

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

9 голосов
/ 25 января 2015

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

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

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

<nul set /p=.9    Hello everyone

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

    Hello Everyone

вместо:

Hello Everyone

Надеюсь, это поможет

7 голосов
/ 19 декабря 2012

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

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

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

5 голосов
/ 26 января 2014

Вот еще один метод, он использует 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
3 голосов
/ 28 июня 2018

С здесь

<nul set /p =Testing testing

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

echo.Message goes here
2 голосов
/ 19 августа 2018

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

echo | set / p = "Hello World"

вот оно:

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

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

2 голосов
/ 13 июля 2018

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

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

Инструменты

Все, что вам нужно, - это .NET , установленный в наше время.

Материалы

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

Steps

  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. Теперь у вас есть хорошая утилита 4 КБ, поэтому вы можете удалить .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)
...