ฉันต้องการเขียนข้อมูลสถานะที่แทนที่บรรทัดสุดท้ายเมื่อฉันทำอะไร
ในตัวอย่างไฟล์ bat ต่อไปนี้ฉันต้องการให้ข้อความStep 2เขียนทับStep 1บนบรรทัดเดียวกันในเอาต์พุตคำสั่ง
echo off
echo Step 1
REM Do some stuff...
echo Step 2
REM do some other stuff...
ฉันต้องการเขียนข้อมูลสถานะที่แทนที่บรรทัดสุดท้ายเมื่อฉันทำอะไร
ในตัวอย่างไฟล์ bat ต่อไปนี้ฉันต้องการให้ข้อความStep 2เขียนทับStep 1บนบรรทัดเดียวกันในเอาต์พุตคำสั่ง
echo off
echo Step 1
REM Do some stuff...
echo Step 2
REM do some other stuff...
คำตอบ:
สคริปต์นี้จะทำสิ่งที่คุณถาม:
@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...
ผมพบว่าคำตอบนี้โดยดูที่รหัสในสคริปต์ชุดห้องสมุดการจัดการตัวอักษรที่เขียนโดยเดฟ Benham เรียกว่าCharLib
ไลบรารีนี้สามารถสร้างตัวละครทั้งหมดในช่วง 1..255
สำหรับข้อมูลเพิ่มเติมดูที่หัวข้อ"สามารถแปลงอักขระเป็นค่า ASCII ได้หรือไม่"
แก้ไข 2017/04/26: ปรากฏว่ารหัสดังกล่าวไม่มีผลงานอีกต่อไป ฉันไม่แน่ใจว่าพฤติกรรมนี้จะเปลี่ยนไปเมื่อใด แต่มันก็ใช้งานได้อย่างแน่นอน CRตัวละครหลังจากที่=ในขณะนี้ได้รับการปล้นโดยsetคำสั่ง อาดูเหมือนว่าเป็นการเปลี่ยนแปลงในการsetทำงานระหว่าง Windows XP และ Windows รุ่นที่ใหม่กว่า ดูคำตอบที่ยอดเยี่ยมในสายการเขียนทับในไฟล์ชุด Windows? (ซ้ำกัน)สำหรับรายละเอียดเพิ่มเติมและตัวอย่างโค้ดเพิ่มเติม
อีกทางเลือกหนึ่งคือการใส่อักขระที่ไม่ใช่ช่องว่างไว้ข้างหน้า!ASCII_13!และจัดให้มีการลบด้วยเช่นกันโดยอาจแทรก backspace (ซึ่งไม่ถูกถอด) ตามด้วยช่องว่างหรือต่อท้ายช่องว่างท้าย สตริงพรอมต์ (ซึ่งไม่ได้ถูกปล้น)
เช่นนี้
@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คำสั่งจะตัด CR และ LF ตัวอักษร (เช่นเดียวกับช่องว่าง) =หลังจากที่ ลองใส่อักขระที่ไม่ใช่ช่องว่างระหว่าง=และ!ACSII_13!
set /p "=Step 2 " <NUL
ในการตอบคำถาม:
@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 2End
ฉันจะกลับมาพร้อมกับอักขระพิเศษ ASCII 8 ซึ่งเป็น backspace เพราะผมไม่ทราบวิธีการเขียนไว้ในคำสั่งผมใช้: ประเมินฟังก์ชั่นซึ่งไหล VBS ฟังก์ชัน Chr () และทำให้ Backspace resultตัวอักษรลงในตัวแปร หากมีคนรู้วิธีที่ดีกว่าโปรดแนะนำ
$host.ui.RawUI.CursorPositionในตัวแปรและเรียกคืนในภายหลังเพื่อให้เคอร์เซอร์กระโดดกลับไปที่ตำแหน่งที่คุณอยู่และเขียนทับเอาต์พุตของคุณ เพียงตัวเลือกสำหรับ PowerShell แต่อาจจะมีการทำความสะอาดบิตกว่าสิ่ง VBS ของคุณ :-)
@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"
สิ่งนี้จะตั้งค่าอักขระ backspace เป็นตัวแปร BSPACE ตอนนี้เพื่อดูผลลัพธ์พิมพ์:
echo ab%BSPACE%c
เอาท์พุท:
ac
คุณสามารถใช้ตัวแปร BSPACE นี้ได้มากกว่าหนึ่งครั้งเพื่อลบอักขระหลายตัว
ทีนี้ถ้าคุณต้องการตั้งค่า carriage return ในตัวแปรให้ใช้
for /F "usebackq" %%a in (คัดลอก / Z "% ~ dpf0" nul) DO (set "cr=%%a")
เพื่อดูผลลัพธ์พิมพ์:
setlocal EnableDelayedExpansion
& echo asfasdhlfashflkashflksa!CR!***
ผลลัพธ์จะเป็น:
***asfasdhlfashflkashflksa
คำตอบของ @davour ด้านบนนั้นสวยงามเช่นกัน แต่คำตอบของ @ timfoden ไม่ได้ผลสำหรับฉัน
set /p "=.!CR!End. " <NUL&echo:
คุณทำไม่ได้ โดยปกติแล้วคุณสามารถทำสิ่งนี้ได้โดยรวมอักขระ carriage-return (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ก่อนที่จะส่งออกขั้นตอนของคุณ จะสั่นไหว แต่วิธีที่คุณเขียนไปทางซ้ายบนเสมอ และปิดบังทุกอย่างที่มองเห็นได้ในคอนโซล (ซึ่งเป็นสาเหตุที่ฉันไม่แนะนำ); ผู้ใช้ส่วนใหญ่ไม่ชอบสิ่งนั้นมากเกินไป
timeout 5จะใช้ได้
for /f %%a in ('copy /Z "%~f0" nul') do set "CR=%%a"
รับอักขระขึ้นบรรทัดใหม่เขียนขั้นตอนถัดไปกลับไปที่จุดเริ่มต้นของบรรทัดเขียนบรรทัดถัดไป:
@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จะยังคงอยู่ ไม่แน่ใจว่าจะแก้ไขอย่างไร
set /p "=Step 2SPACESPACESPACESPACE!Newline!" <NUL set /p "=Step 2!Newline!" <NULแลกเปลี่ยนSPACEกับตัวละคร
คุณต้องการไลบรารี่ของเคอร์เซอร์หน้าจอcursesหรือncursesแต่ฉันไม่คุ้นเคยกับการใช้งานมากเกินไป ทั้งสองไลบรารีได้รับการพัฒนาสำหรับระบบ Unix แต่คุณสามารถค้นหาได้สำหรับ Windows (ในสภาพแวดล้อม CygwinหรือGnuWin32 )
ฉันไม่รู้วิธีง่ายๆในการเข้าถึงไฟล์เหล่านั้นในไฟล์แบตช์สไตล์ DOS คุณอาจจะดีกว่าการเขียนโปรแกรมในภาษาที่คอมไพล์ ลองดูNcurses HOWTOเพื่อรับแนวคิดที่ดีกว่าว่ามันจะมีประโยชน์หรือไม่
ด้วยNotepad ++คุณสามารถแทรกBackspace ←อักขระ (ASCII 0x08) ได้โดยตรงโดยใช้ASCII Codes Insertion Panel (แก้ไข> แผงอักขระ)
โซลูชันของฉันคือการแทรก[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
ภาพหน้าจอ Notepad ++
เอาท์พุต
ความเป็นไปได้อีกอย่างหนึ่งคือการใช้cecho (คำสั่ง echo พร้อมการรองรับสี) เพื่อแทรกCarriage Return ↵อักขระยูนิโค้ด (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
NB: cecho_x64.exeทำงานบนเครื่องของฉันเร็วกว่าcecho.exeมาก