Як перезаписати той самий рядок у командному виході з пакетного файлу


13

Я хочу написати інформацію про стан, яка замінює останній рядок, коли я щось роблю.

У наступному прикладі bat-файлу я хочу, щоб текст Step 2був перезаписаний Step 1у тому ж рядку у командному висновку.

echo off

echo Step 1
REM Do some stuff...

echo Step 2
REM do some other stuff...

Відповіді:


8

Цей сценарій виконає саме те, що ви просили:

@echo off

setlocal enableextensions enabledelayedexpansion
for /f %%a in ('copy /Z "%~dpf0" nul') do set "ASCII_13=%%a"

set /p "=Step 1" <NUL
REM Do some stuff...

set /p "=!ASCII_13!Step 2" <NUL
REM do some other stuff...

Я знайшов цю відповідь, переглянувши код у бібліотеці маніпуляцій із символами пакетного сценарію, написаною Дейвом Бенхем під назвою CharLib .

Ця бібліотека здатна створити всі символи в діапазоні 1..255.

Для отримання додаткової інформації див тему під назвою "Чи можливо перетворити символ у його значення ASCII?"

Редагувати 2017-4-26: Здається, що код вище не працює . Я не впевнений, коли ця поведінка змінилася б, але це, безумовно, працювало. CRХарактер після того , як в =даний час отримує роздягли з допомогою setкоманди. Так, схоже, це зміни в способі setроботи між XP та пізнішими версіями Windows. Дивіться відмінну відповідь у рядку Перезаписати у пакетному файлі Windows? (дублікат) для отримання детальної інформації та додаткових прикладів коду.

Альтернативою є поставити символ без пробілу перед символом !ASCII_13!та домовитись його стирання, можливо, також вставивши зворотну простір (який не знімається) з подальшим пробілом або додавши пробіли до кінця рядок підказок (які не позбавлені)

Наприклад:

@echo off

setlocal enableextensions enabledelayedexpansion
for /f %%a in ('copy /Z "%~dpf0" nul') do set "ASCII_13=%%a"

set /p "=Step 1" <NUL
REM Do some stuff...

set /p "=x!ASCII_13!Step 2 " <NUL
REM do some other stuff...

2
Для мене це просто надрукує "Крок 1 крок 2", а не просто "Крок 2" на екрані.
galmok

@galmok Це почало траплятися і зі мною, але я впевнений, що цього ніколи не використовував (так як у мене сценарій, який раніше працював ідеально, недавно змінився на поведінку, яку ви описуєте.) Схоже, setкоманда тепер знімає будь-яку Символи CR та LF (а також пробіли) після символів =. Спробуйте ввести символ =!ACSII_13!
непробільного місця

Є спосіб зробити все це ... Я насправді прийшов подивитися, чи хтось ще помітив, бо хотів подивитися, чи виявили вони, як далеко це зайшло. ... Чи можна записати ВІДПОВІДЬ при переповненні стека? АБО ... як питання і негайно відповісти на нього? Я думаю, я міг би написати це у формі запитання про те, що ти можеш з цим зробити. Мені треба їсти щось, але я оновлю це за допомогою посилання для вас.
Brent Rittenhouse

Пишіть! ASCII_13! після кроку 1, щоб запобігти зачистці, то на кроці 2 ви будете set /p "=Step 2 " <NUL
Зімба

6

Щоб відповісти на запитання:

@echo off
CALL :EVALUATE "chr(8)"
SET backspace=%result%
<nul set /p =Step 1
:: DO SOME STUFF....
<nul set /p =%backspace%
<nul set /p =2
:: DO SOME OTHER STUFF....
<nul set /p =%backspace%%backspace%%backspace%%backspace%%backspace%%backspace%
<nul set /p =End   
GOTO:EOF



:EVALUATE           -- evaluate with VBS and return to result variable
::                  -- %~1: VBS string to evaluate
:: extra info: http://groups.google.com/group/alt.msdos.batch.nt/browse_thread/thread/9092aad97cd0f917

@IF [%1]==[] ECHO Input argument missing & GOTO :EOF 

@ECHO wsh.echo "result="^&eval("%~1") > %temp%\evaluate_tmp_67354.vbs 
@FOR /f "delims=" %%a IN ('cscript //nologo %temp%\evaluate_tmp_67354.vbs') do @SET "%%a" 
@DEL %temp%\evaluate_tmp_67354.vbs
::ECHO %result%
@GOTO:EOF

Вихід:

End

В принципі, що робить скрипт, є запис Step 1, потім повертається на одне місце, перезаписує 1, а в кінці йде повністю назад і переписує Step 2з End.

Я повертаюся назад із спеціальним символом ASCII 8, який є простором. Оскільки я не знаю, як записати це в cmd, я використовую функцію: EVALUATE, яка запускає функцію VBS Chr (), і вводить символ змінної області в змінну result. Якщо хтось знає кращий спосіб, будь ласка, порадьте.


1
У PowerShell ви також можете зберігати $host.ui.RawUI.CursorPositionзмінну та відновлювати її пізніше, щоб курсор відскочив туди, де ви були, і перезаписав результат. Тільки варіант для PowerShell, але може бути трохи чистішим, ніж ваші речі VBS :-)
mihi

4
@echo off
for /F "tokens=1 delims=# " %%a in ('"prompt #$H# & echo on & for %%b in (1) do rem"') do set "BSPACE=%%a"
<nul set /p =Step 1
ping 127.0.0.1 >nul
<nul set /p =%BSPACE%
<nul set /p =2
ping 127.0.0.1 >nul
<nul set /p =%BSPACE%
<nul set /p =3
ping 127.0.0.1 >nul
<nul set /p =%BSPACE%%BSPACE%%BSPACE%%BSPACE%%BSPACE%%BSPACE%
<nul set /p =End.  
pause

ПОЯСНЕННЯ:

for /F "tokens=1 delims=# " %%a in ('"prompt #$H# & echo on & for %%b in (1) do rem"') do set "BSPACE=%%a"

це встановить символ зворотної області в змінну BSPACE. Тепер, щоб побачити результат, введіть:

echo ab%BSPACE%c

вихід: ac

Ви можете використовувати цю змінну BSPACE більше ніж один раз, щоб видалити кілька символів.

Тепер, якщо ви хочете встановити повернення каретки в змінній, використовуйте

for /F "usebackq" %%a in (копія / Z "% ~ dpf0" нуль) DO (set "cr=%%a")

щоб побачити результат, введіть: setlocal EnableDelayedExpansion & echo asfasdhlfashflkashflksa!CR!***

вихід буде: ***asfasdhlfashflkashflksa

Відповідь @ davour вище також прекрасна, але відповідь @ timfoden не працювала для мене.


@ timfoden відповідь не працює, тому що! CR! має пройти в кінці попереднього кроку. Крім того, замість усіх цих% BSPACE% s ви також можете! CR! і заповніть пробіли:set /p "=.!CR!End. " <NUL&echo:
Зімба

3

Ви не можете. Зазвичай цього можна досягти, включивши у файл символ повернення каретки (0x0D), який поверне курсор до першого стовпця в тому ж рядку. Але в цьому випадку це не працює; CR просто мовчки їдять.

Окрім того, введення CR у своєрідне складне і, принаймні, тут задіяний текстовий редактор. Я б запропонував вам написати невелику корисну програму, яка зробить це для вас, насправді це не дуже складно. Наступна маленька програма C може бути достатньою (якщо вам не потрібен Unicode):

#include <stdio.h>

int main(int argc, char* argv[]) {
  if (argc < 2) return 1;
  printf("\r%s", argv[1]);
}

Це не що інше, як друк символу CR, а потім текст, який ви вказали як свій перший аргумент. Використання наступним чином:

@echo off
<nul set /P X=Step 1
pause>nul 2>nul
over.exe "Step 2"

Останній рядок - це виклик до цієї програми. Другий рядок - це звичайна партійна ідіома для друку тексту без розриву кінцевої лінії (що важливо в цьому випадку, оскільки в іншому випадку ви не змогли перезаписати рядок). Ти можеш так само добре використовувати програму вище, як і в цьому місці.

Легко хакітним способом, але єдиним, де ви можете бути впевнені, де ви опинитесь, було б використовувати clsперед початком крокового результату. Мерехтить, але таким чином ви завжди пишете вгорі ліворуч. І хапайте все, що було видно на консолі (саме тому я б не рекомендував це); більшості користувачів це не дуже подобається.


Гаразд, у мене була підозра, що це не можливо зробити з чистим командним рядком. Якщо я хочу зробити так, щоб утиліта зробила це, я можу також поставити всю річ у утиліту. Мені дуже хотілося - це лише видимий відлік часу, який чекає 5 секунд, відлічуючи кожну секунду до кінця.
трепет

4
трепет: Якщо ви перебуваєте на Vista чи пізніші версії, тоді timeout 5ви працюєте.
Джої

Чудово! Дякую тобі! timeout 5 працює!
трепет

4
Я повинен був опублікувати свій справжній випуск вперше ...
побоюванням

Звичайно, ви можете; просто додайте повернення вагона після кроку 1! Крім того, ось якийсь код, щоб повернути перевезення без участі текстового редактора:for /f %%a in ('copy /Z "%~f0" nul') do set "CR=%%a"
Зімба

1

Отримати символ нового рядка, написати наступний крок, повернутися до початку рядка, написати наступний рядок:

@echo off
cls
setlocal enabledelayedexpansion
echo Here's how it's done:

for /f %%a in ('copy /Z "%~f0" nul') do set "Newline=%%a"
set /p "=Step 1!Newline!" <NUL
REM Do some stuff...
ping -n 2 localhost > nul
set /p "=Step 2!Newline!" <NUL
ping -n 2 localhost > nul
set /p "=Step 3 " <NUL
REM do some other stuff...
ping -n 2 localhost > nul
echo:
echo Done.

Це буде працювати лише в тому випадку, якщо Step 1 Step 2 Step 3всі мають однакову довжину. Якщо ні, текст першого set /pзалишається. Не знаєте, як це виправити.
Ste

Цю проблему можна вирішити, використовуючи додаткові символи пробілу в наступному рядку. щоб охопити будь-які попередні символи. Приклад set /p "=Step 2SPACESPACESPACESPACE!Newline!" <NUL на відміну від set /p "=Step 2!Newline!" <NUL. Обмін SPACEна персонажа.
Ste

Якщо попередні рядки довші, то додайте пробіли для видалення зайвих символів або зворотної області від кінця рядка до початку або просто простору для додаткових символів.
Зімба

0

Вам знадобиться бібліотека курсорних екранів на кшталт cursesабо ncurses, але я не надто знайомий з їх використанням. Обидві бібліотеки були розроблені для систем Unix, але їх можна знайти для Windows (у середовищі Cygwin або GnuWin32 ).

Я не знаю жодного простого способу отримати доступ до них у пакетному файлі стилю DOS. Можливо, вам буде краще програмувати на компільованій мові. Погляньте на Ncurses HOWTO, щоб краще зрозуміти, чи буде вона корисна.


прокльони в значній мірі лише для терміналів і емуляторів терміналів. Вони насправді не відображають API рідної консолі Windows.
Joey

НЕ потребує зовнішніх бібліотек; прекрасно працює з інструментами CMD.
Зімба

0

Рішення 1

За допомогою Notepad ++ можна вставити Backspace ←символ (ASCII 0x08) безпосередньо, використовуючи панель вставки кодів ASCII (Редагувати> Панель символів).

Моє рішення - вставити [BS]символ безпосередньо, а потім, як і інші рішення, розміщені тут, використовувати його кілька разів, щоб видалити попередні символи:

Код

@ECHO OFF

SET "BACKSPACE_x7=[BS][BS][BS][BS][BS][BS][BS]"

SET /P "DUMMY_VAR=Step 1" < NUL
REM Do some stuff...

SET /P "DUMMY_VAR=%BACKSPACE_x7%Step 2" < NUL
REM Do some other stuff...

GOTO :EOF

Скріншот блокнота ++

Перезапис пакетів Windows


Вихідні дані

Вихід CMD


Рішення 2

Інша можливість - використовувати cecho (команда echo з підтримкою кольорів) для вставки Carriage Return ↵символу unicode (U + 000D):

Код

@ECHO OFF

SET CARRIAGE_RETURN={\u000D}

cecho Step 1
REM Do some stuff...

cecho %CARRIAGE_RETURN%Step 2
REM Do some other stuff...

GOTO :EOF

Примітка: cecho_x64.exeна моїй машині працює значно швидше, ніж cecho.exe.

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