วิธีการเขียนทับบรรทัดเดียวกันในเอาต์พุตคำสั่งจากไฟล์แบตช์


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...

ผมพบว่าคำตอบนี้โดยดูที่รหัสในสคริปต์ชุดห้องสมุดการจัดการตัวอักษรที่เขียนโดยเดฟ 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...

2
สำหรับฉันนี่แค่พิมพ์ "ขั้นตอนที่ 1 ขั้นตอนที่ 2" แทนที่จะมีเพียง "ขั้นตอนที่ 2" บนหน้าจอ
galmok

@galmok สิ่งนี้ก็เริ่มเกิดขึ้นกับฉันเช่นกัน แต่ฉันแน่ใจว่ามันไม่เคยใช้ (เพราะฉันมีสคริปต์ที่ใช้ในการทำงานอย่างสมบูรณ์เมื่อเร็ว ๆ นี้ได้เปลี่ยนไปเป็นพฤติกรรมที่คุณอธิบาย) ดูเหมือนว่าsetคำสั่งจะตัด CR และ LF ตัวอักษร (เช่นเดียวกับช่องว่าง) =หลังจากที่ ลองใส่อักขระที่ไม่ใช่ช่องว่างระหว่าง=และ!ACSII_13!
timfoden

มีวิธีการทำทั้งหมดนี้ ... ฉันมาเพื่อดูว่ามีใครสังเกตเห็นหรือไม่เพราะฉันต้องการดูว่าพวกเขาค้นพบว่ามันไปไกลแค่ไหน ... ฉันสามารถเขียนคำตอบลงบนสแต็คล้นได้หรือไม่? หรือ .. เช่นคำถามและตอบทันทีหรือไม่ ฉันคิดว่าฉันสามารถเขียนในรูปแบบคำถามเกี่ยวกับสิ่งที่คุณสามารถทำกับมัน .. ฉันต้องไปกินอะไร แต่ฉันจะอัปเดตพร้อมลิงค์สำหรับคุณ
Brent Rittenhouse

เขียน! ASCII_13! หลังจากขั้นตอนที่ 1 เพื่อป้องกันการลอกดังนั้นในขั้นตอนที่ 2 คุณจะรหัส:set /p "=Step 2 " <NUL
Zimba

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 2End

ฉันจะกลับมาพร้อมกับอักขระพิเศษ ASCII 8 ซึ่งเป็น backspace เพราะผมไม่ทราบวิธีการเขียนไว้ในคำสั่งผมใช้: ประเมินฟังก์ชั่นซึ่งไหล VBS ฟังก์ชัน Chr () และทำให้ Backspace 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"

สิ่งนี้จะตั้งค่าอักขระ 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 ไม่ได้ผลสำหรับฉัน


@ คำตอบของ timfoden ไม่ทำงานเพราะ! CR! ควรจบขั้นตอนก่อนหน้า นอกจากนี้แทนที่จะเป็น% BSPACE% s ทั้งหมดคุณสามารถทำได้! CR! และเติมด้วยช่องว่าง:set /p "=.!CR!End. " <NUL&echo:
Zimba

3

คุณทำไม่ได้ โดยปกติแล้วคุณสามารถทำสิ่งนี้ได้โดยรวมอักขระ 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ก่อนที่จะส่งออกขั้นตอนของคุณ จะสั่นไหว แต่วิธีที่คุณเขียนไปทางซ้ายบนเสมอ และปิดบังทุกอย่างที่มองเห็นได้ในคอนโซล (ซึ่งเป็นสาเหตุที่ฉันไม่แนะนำ); ผู้ใช้ส่วนใหญ่ไม่ชอบสิ่งนั้นมากเกินไป


ตกลงฉันสงสัยว่ามันเป็นไปไม่ได้ที่จะทำกับบรรทัดคำสั่งที่สะอาด ถ้าฉันต้องการให้ยูทิลิตี้ทำสิ่งนี้ฉันก็อาจใส่ทุกอย่างไว้ในยูทิลิตี้ก็ได้ สิ่งที่ฉันต้องการจริงๆคือการนับถอยหลังที่มองเห็นได้ซึ่งรอ 5 วินาทีนับถอยหลังทุกวินาทีจนเสร็จ
กลัว

4
awe: ถ้าคุณอยู่บน Vista หรือใหม่กว่านั้นtimeout 5จะใช้ได้
Joey

ที่ดี! ขอบคุณ! หมดเวลา 5 งาน!
กลัว

4
ฉันควรจะได้โพสต์ปัญหาที่แท้จริงของฉันเป็นครั้งแรก ...
กลัว

แน่นอนคุณสามารถ; เพียงเพิ่มการรับคืนหลังจากขั้นตอนที่ 1! นอกจากนี้ต่อไปนี้เป็นรหัสบางส่วนสำหรับการรับคืนสินค้าโดยไม่เกี่ยวข้องกับเครื่องมือแก้ไขข้อความ:for /f %%a in ('copy /Z "%~f0" nul') do set "CR=%%a"
Zimba

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จะยังคงอยู่ ไม่แน่ใจว่าจะแก้ไขอย่างไร
ผลิต

ปัญหานั้นสามารถแก้ไขได้โดยใช้อักขระช่องว่างเพิ่มเติมในการแจ้งครั้งถัดไป เพื่อครอบคลุมอักขระก่อนหน้าใด ๆ ตัวอย่างเช่น เมื่อเทียบกับset /p "=Step 2SPACESPACESPACESPACE!Newline!" <NUL set /p "=Step 2!Newline!" <NULแลกเปลี่ยนSPACEกับตัวละคร
ผลิต

หากบรรทัดก่อนหน้ายาวกว่านั้นให้เพิ่มช่องว่างเพื่อเว้นว่างอักขระพิเศษหรือ backspace จากจุดสิ้นสุดบรรทัดไปยังจุดเริ่มต้นหรือเพียงแค่ถอยกลับไปที่อักขระพิเศษ
Zimba

0

คุณต้องการไลบรารี่ของเคอร์เซอร์หน้าจอcursesหรือncursesแต่ฉันไม่คุ้นเคยกับการใช้งานมากเกินไป ทั้งสองไลบรารีได้รับการพัฒนาสำหรับระบบ Unix แต่คุณสามารถค้นหาได้สำหรับ Windows (ในสภาพแวดล้อม CygwinหรือGnuWin32 )

ฉันไม่รู้วิธีง่ายๆในการเข้าถึงไฟล์เหล่านั้นในไฟล์แบตช์สไตล์ DOS คุณอาจจะดีกว่าการเขียนโปรแกรมในภาษาที่คอมไพล์ ลองดูNcurses HOWTOเพื่อรับแนวคิดที่ดีกว่าว่ามันจะมีประโยชน์หรือไม่


คำสาปนั้นค่อนข้างมากสำหรับเทอร์มินัลและเทอร์มินัลอีมูเลเตอร์เท่านั้น พวกเขาไม่ได้จับคู่กับ API คอนโซลของ Windows จริงๆ
Joey

ไม่จำเป็นต้องใช้ไลบรารีภายนอก ทำงานได้ดีกับเครื่องมือ CMD
Zimba

0

โซลูชันที่ 1

ด้วย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 ++

ชุด Windows เขียนทับ


เอาท์พุต

เอาต์พุต CMD


โซลูชันที่ 2

ความเป็นไปได้อีกอย่างหนึ่งคือการใช้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มาก

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.