9

Я хочу написать некоторую информацию о состоянии, которая заменяет последнюю строку, когда я что-то делаю.

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

echo off

echo Step 1
REM Do some stuff...

echo Step 2
REM do some other stuff...

5 ответов5

6

Этот скрипт будет делать именно то, что вы просили:

@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...
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, который является backspace. Поскольку я не знаю, как написать это в cmd, я использую функцию:EVALUATE, которая запускает функцию VBS Chr() и помещает символ возврата в переменную result . Если кто-то знает лучший способ, пожалуйста, сообщите.

3

Ты не можешь Обычно этого можно добиться, добавив в файл символ возврата каретки (0x0D), который вернет курсор к первому столбцу в той же строке. Но в этом случае это не работает; ЧР просто молча едят.

Кроме того, получить 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 до вашего шага вывода. Будет мерцать, но так вы всегда пишете в верхнем левом углу. И ударить все, что было видно в консоли (вот почему я бы не рекомендовал это); большинству пользователей это не нравится.

1
@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 ( copy /Z "% ~ dpf0" nul ) DO (set "cr=%%a")

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

вывод будет:***asfasdhlfashflkashflksa

Ответ @ davour выше также красив, но ответ @ timfoden мне не помог.

0

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

Я не знаю простого способа получить к ним доступ в пакетном файле в стиле DOS. Возможно, вам лучше программировать на скомпилированном языке. Взгляните на Ncurses HOWTO, чтобы лучше понять, будет ли это полезно.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .