Câu trả lời:
Kịch bản này sẽ làm chính xác những gì bạn yêu cầu:
@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...
Tôi tìm thấy câu trả lời này bằng cách xem mã trong một thư viện thao tác ký tự tập lệnh được viết bởi Dave Benham có tên là CharLib .
Thư viện này có thể tạo tất cả các ký tự trong phạm vi 1..255.
Để biết thêm thông tin, hãy xem chủ đề có tên "Có thể chuyển đổi một ký tự thành giá trị ASCII của nó không?"
Chỉnh sửa 2017-4-26: Có vẻ như đoạn mã trên không còn hoạt động . Tôi không chắc chắn khi hành vi này sẽ thay đổi, nhưng nó chắc chắn được sử dụng để làm việc. Các CR
nhân vật sau khi =
bị tước set
lệnh. Ah, nó dường như là một sự thay đổi trong cách set
làm việc giữa XP và các phiên bản Windows mới hơn. Xem câu trả lời xuất sắc trong dòng Ghi đè trong tệp bó Windows? (trùng lặp) để biết thêm chi tiết và thêm ví dụ mã.
Sau đó, một cách khác là đặt một ký tự không phải khoảng trắng trước !ASCII_13!
và sắp xếp để xóa nó, có lẽ bằng cách chèn một khoảng trống (không bị xóa) theo sau là khoảng trắng hoặc bằng cách thêm khoảng trắng vào cuối chuỗi dấu nhắc (không bị tước.)
Ví dụ như thế này:
@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...
set
lệnh tại dải bất kỳ Các ký tự CR và LF (cũng như khoảng trắng) sau =
. Hãy thử đặt một ký tự không phải khoảng trắng giữa =
và!ACSII_13!
set /p "=Step 2 " <NUL
Để trả lời câu hỏi:
@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
Đầu ra:
End
Về cơ bản, những gì kịch bản thực hiện, là viết Step 1
, sau đó quay ngược lại một nơi, ghi đè 1
, và cuối cùng đi hoàn toàn trở lại và ghi đè Step 2
với End
.
Điều này quay trở lại tôi làm với ký tự ASCII 8 đặc biệt là backspace. Vì tôi không biết cách viết nó trong cmd, tôi sử dụng hàm: EVALUATE chạy hàm VBS Chr () và đặt ký tự backspace vào biến result
. Nếu ai đó biết một cách tốt hơn, xin vui lòng tư vấn.
$host.ui.RawUI.CursorPosition
vào một biến và khôi phục nó sau để con trỏ quay trở lại vị trí của bạn và ghi đè đầu ra của bạn. Chỉ là một tùy chọn cho PowerShell, nhưng có thể sạch hơn một chút so với công cụ VBS của bạn :-)
@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
GIẢI TRÌNH:
for /F "tokens=1 delims=# " %%a in ('"prompt #$H# & echo on & for %%b in (1) do rem"') do set "BSPACE=%%a"
điều này sẽ đặt ký tự backspace thành biến BSPACE. Bây giờ để xem kết quả, gõ:
echo ab%BSPACE%c
đầu ra:
ac
bạn có thể sử dụng biến BSPACE này nhiều lần để xóa nhiều ký tự.
Bây giờ, nếu bạn muốn đặt lợi nhuận vận chuyển trong một biến, hãy sử dụng
for /F "usebackq" %%a in (
sao chép / Z "% ~ dpf0" nul) DO (set "cr=%%a")
để xem kết quả, gõ:
setlocal EnableDelayedExpansion
& echo asfasdhlfashflkashflksa!CR!***
đầu ra sẽ là:
***asfasdhlfashflkashflksa
Câu trả lời của @ davour ở trên cũng rất hay nhưng câu trả lời của @ timfoden không phù hợp với tôi.
set /p "=.!CR!End. " <NUL&echo:
Bạn không thể. Thông thường, bạn có thể đạt được loại điều này bằng cách bao gồm ký tự trả về vận chuyển (0x0D) trong tệp sẽ đưa con trỏ trở lại cột đầu tiên trong cùng một dòng. Nhưng trong trường hợp này nó không hoạt động; CR chỉ âm thầm ăn.
Hơn nữa, việc đưa CR vào đó khá khó khăn và ít nhất ở đây có sự tham gia của một trình soạn thảo văn bản. Tôi khuyên bạn nên viết một chương trình tiện ích nhỏ sẽ làm điều này cho bạn, nó thực sự không khó lắm. Chương trình C nhỏ sau đây có thể đủ (nếu bạn không cần Unicode):
#include <stdio.h>
int main(int argc, char* argv[]) {
if (argc < 2) return 1;
printf("\r%s", argv[1]);
}
Nó không làm gì khác hơn là in một ký tự CR và sau đó là văn bản bạn chỉ định làm đối số đầu tiên. Cách sử dụng như sau:
@echo off
<nul set /P X=Step 1
pause>nul 2>nul
over.exe "Step 2"
Dòng cuối cùng là cuộc gọi đến chương trình đó. Dòng thứ hai là thành ngữ lô bình thường để in văn bản mà không bị ngắt dòng (điều này rất quan trọng trong trường hợp này vì nếu không bạn không thể ghi đè lên dòng). Bạn cũng có thể sử dụng chương trình ở trên cũng như ở nơi đó.
Một cách nhẹ nhàng, nhưng cách duy nhất mà bạn có thể chắc chắn nơi bạn kết thúc, sẽ là sử dụng cls
trước bước đầu ra của bạn. Sẽ nhấp nháy nhưng theo cách đó bạn luôn viết cho phía trên bên trái. Và ghi đè mọi thứ có thể nhìn thấy trong bảng điều khiển (đó là lý do tại sao tôi không khuyên dùng nó); hầu hết người dùng không thích điều đó quá nhiều.
timeout 5
sẽ hoạt động.
for /f %%a in ('copy /Z "%~f0" nul') do set "CR=%%a"
Nhận ký tự dòng mới, viết bước tiếp theo, quay lại bắt đầu dòng, viết dòng tiếp theo:
@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
tất cả đều có cùng chiều dài. Nếu không phải là văn bản đầu tiên set /p
vẫn còn. Không chắc chắn làm thế nào để khắc phục điều này.
set /p "=Step 2SPACESPACESPACESPACE!Newline!" <NUL
trái ngược với set /p "=Step 2!Newline!" <NUL
. Trao đổi SPACE
cho nhân vật.
Bạn sẽ cần một thư viện con trỏ màn hình như curses
hoặc ncurses
, nhưng tôi không quá quen thuộc với việc sử dụng chúng. Cả hai thư viện đều được phát triển cho các hệ thống Unix, nhưng bạn có thể tìm thấy chúng cho Windows (trong môi trường Cygwin , hoặc GnuWin32 ).
Tôi không biết bất kỳ cách dễ dàng nào để truy cập chúng trong tệp bó kiểu DOS. Bạn có thể tốt hơn hết là lập trình bằng một ngôn ngữ được biên dịch. Hãy xem Ncurses HOWTO để có ý tưởng tốt hơn về việc nó sẽ hữu ích.
Với Notepad ++ , có thể chèn Backspace ←trực tiếp ký tự (ASCII 0x08) bằng cách sử dụng Bảng chèn mã ASCII (Chỉnh sửa> Bảng ký tự).
Giải pháp của tôi là chèn [BS]
ký tự trực tiếp và sau đó, giống như các giải pháp khác được đăng ở đây, sử dụng nó nhiều lần để xóa các ký tự trước đó:
Mã
@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
Ảnh chụp màn hình Notepad ++
Đầu ra
Một khả năng khác là sử dụng cecho (lệnh echo có hỗ trợ màu sắc) để chèn một Carriage Return ↵ký tự unicode (U + 000D):
Mã
@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
NB: cecho_x64.exe
chạy nhanh hơn đáng kể trên máy của tôi hơn cecho.exe
.