Пакет Windows: відлуння без нового рядка


231

Який пакетний еквівалент Windows команди оболонки Linux, echo -nякий придушує новий рядок в кінці виводу?

Ідея полягає в тому, щоб записати на одному рядку всередині циклу.



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:\>

Джерело


86
Труба дуже повільна, оскільки вона створює дві додаткові завдання cmd, тим швидше <nul set /p =Hello. set /pне може повторювати знак рівності як перший символ, ні пробіли / вкладки.
jeb

11
У моїй системі це майже в 15 разів швидше
1111

28
Додайте цитати навколо "Hello World", щоб запобігти сторонній простір після d.
Брайан

13
Попередження: Це змінить ERRORLEVEL на 1. Див. Відповідь @xmechanix.
CoperNick

6
@ user246694 < nul- це переспрямування з NULпристрою. Він нічого не містить, але цього достатньо, set /pщоб перестати чекати введення користувачем
jeb

100

Використовуючи: echo | set /p=або <NUL set /p=обидва будуть працювати для придушення нового рядка.

Однак це може бути дуже небезпечно при написанні більш досконалих сценаріїв, коли перевірка ERRORLEVEL стає важливою, оскільки параметр set /p=без вказівки імені змінної встановить ERRORLEVEL на 1.

Кращим підходом було б просто використовувати ім’я змінної манекена типу:
echo | set /p dummyName=Hello World

Це дозволить отримати саме те, що ви хочете, без будь-яких підступних речей, що відбуваються у фоновому режимі, як мені довелося з’ясувати важкий шлях, але це працює лише з трубопровідною версією; <NUL set /p dummyName=Helloвсе ще підніме ERRORLEVEL до 1.


20
Попередження: Ця команда встановить ERRORLEVEL на 0. Якщо ERRORLEVEL була більшою, то 0 змінить ERRORLEVEL на 0. Це також може бути небезпечним при написанні більш досконалих сценаріїв. (але +1 для відповіді)
CoperNick

Таким чином, вам, як правило, потрібна ЯКЩО ПОМИЛКА == 0 (...) ELSE (...) лише для того, щоб не зашкодити навколишньому середовищу в тих умовах. Шиш.
SilverbackNet

28

Простий метод SET / P має обмеження, які дещо відрізняються між версіями Windows.

  • Провідні котирування можуть бути позбавлені

  • Білий простір може бути позбавлений

  • Ведучий =викликає синтаксичну помилку.

Див. Http://www.dostips.com/forum/viewtopic.php?f=3&t=4209 для отримання додаткової інформації.

jeb опублікував розумне рішення, яке вирішує більшість проблем у тексті виводу без передачі рядків, навіть з провідним простором або = Я вдосконалив метод, щоб він міг безпечно друкувати абсолютно будь-яку дійсну пакетну рядок без нового рядка, у будь-якій версії Windows від XP і далі. Зауважте, що :writeInitializeметод містить рядковий літерал, який може не надто добре розміщуватися на сайті. Додано зауваження, яке описує, якою має бути послідовність символів.

Методи :writeта :writeVarметоди оптимізовані таким чином, що лише рядки, що містять проблемних провідних символів, записуються за допомогою моєї модифікованої версії методу COPY від jeb. Непромінні рядки записуються за допомогою більш простого та швидшого методу 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

1
Приємно бачити дуже потужне рішення, яке може впоратися з усіма персонажами
jeb

2
Я хотів би зазначити, що якщо комп'ютер має мережеве підключення до Інтернету, то приблизно ця частина пакетного коду може бути використана для завантаження та встановлення python чи будь-чого іншого на комп’ютер, що дозволяє позбутися партії. Пакет - це весело, однак його строкові можливості найкращі для вихідних.
n611x007

@dbenham на рядку 6 "echo (" це функціонально те саме, що "echo" - не бачили цього раніше.)
Пропустити R

2
@SkipR - Так, він функціонально такий же, як ECHO., за винятком випадківECHO. , коли може бути невдалий при незрозумілих обставинах . Існує маса інших форм, які також можуть провалюватися в незрозумілих ситуаціях. Єдине, що завжди працює - це ECHO(.
dbenham

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
барлоп

9

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

хитрість полягає в тому, що символи зворотної області, які ви можете викликати в текстовому редакторі EDIT for DOS. Щоб створити його в EDIT, натисніть ctrlP + ctrlH . Я б вставив його тут, але ця веб-сторінка не може відображати його. Хоча це видно на Блокноті (він похмурий, як маленький чорний прямокутник з білим колом у центрі)

Отже, ви пишете це:

<nul set /p=.9    Hello everyone

Точка може бути будь-якою таблицею, вона лише там повинна сказати SET / P, що текст починається там, перед пробілами, а не на " Привіт ". " 9 " - це зображення діаграми зворотної області, яку я не можу відобразити тут. Ви повинні поставити його замість 9, і він видалить " . ", Після чого ви отримаєте це:

    Hello Everyone

замість:

Hello Everyone

Я сподіваюся, що це допомагає


2
Я забув сказати, він працює в Windows 7. Він не працюватиме в командному рядку, лише в пакетній. Для тих, хто не отримує чар, завантажте цей приклад: pecm.com.sapo.pt/SET_with_backspace_char.txt
Педро,

Також стосується Ехо
Бен Персонік

... Отже, зробивши досить проклятий ретельний пошук, я не знайшов цього ні в Інтернеті. Це може бути один раз, коли я насправді щось виявив, і від німої удачі. Для тих, хто не знає, ви МОЖЕТЕ ввести контрольні символи, якщо ви переведете підказку cmd у застарілий режим і використовуєте правильний шрифт. ... Але якщо ви просто перенаправляєте що-небудь на файл або> con, це теж працює. Серйозно. Вставте це ТОЧНО у свій командний рядок: "ехо ← c◙◙ ○○ Harharhar !! ◙ ○○ ------------- ◙◙ ○○ Я найгірший !?:" (○ ♪ ! ○ NOPE • ♪ ○ Я відчуваю себе чудово Hazzah-ле-полокоть ◙◙ ○ Я programmeer почуй мене ... something.◙> проти »!.
Brent Rittenhouse

Гаразд, я сподіваюся, що я дізнався це раніше, ніж будь-хто інший, але ... це, мабуть, залежить від того, щоб не знаходитись на кодовій сторінці унікоду. Ви можете зберегти початковий у змінній do chcp 437, встановити набір у змінну або вивести його, а потім переключити назад (і він все одно повинен виводитись). Я все ще граю з цим.
Brent Rittenhouse

Також хтось має уявлення, чому ← c очищає екран ?! Я не можу знайти примірник цього в будь-якій мережі. Спеціально це поєднання, хоча, здається, ви також можете мати пробіл між двома символами. Для будь-якого іншого персонажа, здається, просто .. видалити перший символ. Я не розумію ...
Brent Rittenhouse

7

Ви можете видалити новий рядок за допомогою "tr" з gnuwin32 ( пакет coreutils )

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

До речі, якщо ви робите багато сценаріїв, gnuwin32 - це золота мина.


Я також пропоную встановити 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 . . .

Цей нижче є дещо іншим, не працює так, як хоче ОП, але цікавий тим, що кожен результат замінює попередній результат, що імітує лічильник.

@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

Можливо, це те, що ти шукаєш, це старий шкільний сценарій ...: 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%" використовує зворотний простір для додавання пробілів після "Приклад повідомлення" для відокремлення "Виведення команди" Пауза ", фактично не додаючи видимого символу після" Приклад повідомлення ". Однак це також можливо при звичайному знаку відсотка.


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

Зроби сам 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. Тепер у вас є приємна утиліта 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)

Я надихнувся вашою відповіддю і створив цей маленький інструмент за допомогою Go і це супровідне завдання для Azure Pipelines. Він просто захоплює stdout, який прокладений, і виводить його у певному форматі, який повинен підбирати збірка. Дякую!
riezebosch

2

Я зробив функцію з ідеї @arnep:

echo | set / p = "Привіт, світ"

ось:

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

Використовуйте його, call :SL "Hello There"
я знаю, що це нічого особливого, але мені потрібно було так довго думати про це, я зрозумів, що опублікую його тут.


1

Зразок 1: Це працює і створює код виходу = 0. Це добре. Зверніть увагу на "." , безпосередньо після відлуння.

C: \ Користувачі \ phife.dog \ gitrepos \ 1 \ repo_abc \ scriptpts #
@echo. | set / p JUNK_VAR = Це повідомлення відображається як Linux echo -n відображатиме його ... & echo% ERRORLEVEL%

Це повідомлення відображається так, як Linux echo -n відобразило б його ... 0

Приклад 2: Це працює, але створює вихідний код = 1. Це погано. Зверніть увагу на відсутність ".", Після відлуння. У цьому, очевидно, є різниця.

C: \ Користувачі \ phife.dog \ gitrepos \ 1 \ repo_abc \ scriptpts #
@echo | set / p JUNK_VAR = Це повідомлення відображається як Linux echo -n відображатиме його ... & echo% ERRORLEVEL%

Це повідомлення, яке відображається так, як Linux echo -n відобразило б його ... 1


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

0

Я вважаю, що такого варіанту немає. Або ви можете спробувати це

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

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символами. Це також дозволить вам легко записати кілька разів в один рядок, якщо ви показуєте якусь смугу прогресу або щось із використанням символів, як це було, очевидно, ОП.


@jiggunjer Ви впевнені? printfcmd"'printf' is not recognized as an internal or external command, operable program or batch file."
Інструмент з

printfне є рідним для Windows. Це питання Windows.
kayleeFrye_onDeck

1
@kayleeFrye_onDeck Я припускаю, що ваш коментар спрямований на jiggunjer , а не на мене; Я пропоную в своєму запитанні, що C і C ++ можуть використовуватися як досить незалежна від платформи альтернатива командам оболонки у випадках, коли форматування важливе.
SeldomNeedy

1
Пробач, батьку, бо я скупився.
kayleeFrye_onDeck

Але тоді вхід до оболонки потрібно правильно проаналізувати. Наприклад, як така програма надрукує лапки?
Алекс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.