Cara menimpa baris yang sama dalam output perintah dari file batch

13

Saya ingin menulis beberapa info status yang menggantikan baris terakhir ketika saya melakukan sesuatu.

Dalam contoh file bat berikut, saya ingin teks Step 2untuk ditimpa Step 1pada baris yang sama pada output perintah.

echo off

echo Step 1
REM Do some stuff...

echo Step 2
REM do some other stuff...
perasaan kagum
sumber

Jawaban:

8

Script ini akan melakukan persis apa yang Anda minta:

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

Saya menemukan jawaban ini dengan melihat kode di perpustakaan manipulasi karakter skrip batch yang ditulis oleh Dave Benham disebut CharLib .

Perpustakaan ini mampu membuat semua karakter dalam kisaran 1..255.

Untuk info lebih lanjut, lihat utas yang berjudul "Apakah mungkin untuk mengubah karakter ke nilai ASCII-nya?"

Sunting 2017-4-26: Tampaknya kode di atas tidak lagi berfungsi . Saya tidak yakin kapan perilaku ini akan berubah, tetapi sudah pasti berhasil. The CRkarakter setelah =sekarang akan dilucuti oleh setperintah. Ah, tampaknya ada perubahan cara setkerja antara XP dan versi Windows yang lebih baru. Lihat jawaban luar biasa pada baris Timpa di file kumpulan Windows? (duplikat) untuk detail lebih lanjut dan contoh kode tambahan.

Alternatif kemudian adalah menempatkan karakter non-spasi putih sebelum !ASCII_13!dan mengaturnya untuk dihapus juga, mungkin juga dengan memasukkan spasi mundur (yang tidak dilucuti) diikuti oleh spasi atau dengan menambahkan spasi ke ujung string cepat (yang tidak dilucuti.)

Misal seperti ini:

@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...
timfoden
sumber
2
Bagi saya, ini hanya mencetak "Langkah 1 Langkah 2" bukannya hanya "Langkah 2" di layar.
galmok
@galmok Ini sudah mulai terjadi pada saya juga, tapi saya yakin itu tidak pernah digunakan (karena saya memiliki skrip yang dulu berfungsi dengan sempurna, baru-baru ini telah berubah menjadi perilaku yang Anda gambarkan.) Tampaknya setperintah itu sekarang menghapus semua Karakter CR dan LF (serta spasi) setelah =. Coba letakkan karakter non-spasi putih antara =dan!ACSII_13!
timfoden
Ada cara untuk melakukan semua ini ... Saya benar-benar datang untuk melihat apakah ada orang lain yang memperhatikan, karena saya ingin melihat apakah mereka telah menemukan seberapa jauh jaraknya. ... Dapatkah saya menulis JAWABAN pada stack overflow? ATAU .. suka Pertanyaan dan langsung menjawabnya? Saya kira saya bisa menulis dalam bentuk pertanyaan tentang apa yang dapat Anda lakukan dengannya .. Saya harus makan sesuatu tetapi saya akan memperbarui ini dengan tautan untuk Anda.
Brent Rittenhouse
Tulis! ASCII_13! setelah Langkah 1 untuk mencegah pengupasan, maka pada langkah 2 Anda akan membuat kode:set /p "=Step 2 " <NUL
Zimba
6

Untuk menjawab pertanyaan:

@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

Keluaran:

End

Pada dasarnya, apa script tidak, adalah menulis Step 1, kemudian kembali satu tempat, menimpa 1, dan pada akhirnya pergi benar-benar kembali dan menimpa Step 2dengan End.

Ini akan kembali saya lakukan dengan karakter ASCII 8 khusus yang merupakan backspace. Karena saya tidak tahu bagaimana menulisnya dalam cmd, saya menggunakan fungsi: EVALUATE yang menjalankan fungsi VBS Chr (), dan menempatkan karakter backspace ke dalam variabel result. Jika seseorang tahu cara yang lebih baik, mohon saran.

Davor Josipovic
sumber
1
Di PowerShell, Anda juga dapat menyimpan $host.ui.RawUI.CursorPositionke dalam variabel dan mengembalikannya nanti agar kursor melompat kembali ke tempat Anda berada dan menimpa output Anda. Hanya opsi untuk PowerShell, tetapi mungkin sedikit lebih bersih daripada barang VBS Anda :-)
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

PENJELASAN:

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

ini akan mengatur karakter backspace ke dalam variabel BSPACE. Sekarang untuk melihat hasilnya, ketik:

echo ab%BSPACE%c

keluaran: ac

Anda dapat menggunakan variabel BSPACE ini lebih dari sekali untuk menghapus banyak karakter.

Sekarang, jika Anda ingin mengatur carriage return dalam variabel, gunakan

for /F "usebackq" %%a in (copy / Z "% ~ dpf0" nul) DO (set "cr=%%a")

untuk melihat hasilnya, ketik: setlocal EnableDelayedExpansion & echo asfasdhlfashflkashflksa!CR!***

hasilnya adalah: ***asfasdhlfashflkashflksa

@ davour jawaban di atas juga indah tetapi jawaban @ timfoden tidak bekerja untuk saya.

Sourav Ghosh
sumber
@ jawaban timfoden tidak berhasil karena! CR! harus pergi pada akhir langkah sebelumnya. Selain itu, alih-alih semua% BSPACE% s itu, Anda juga bisa! CR! dan isi dengan spasi putih:set /p "=.!CR!End. " <NUL&echo:
Zimba
3

Kamu tidak bisa Biasanya Anda dapat mencapai hal semacam ini dengan memasukkan karakter carriage-return (0x0D) dalam file yang akan mengembalikan kursor ke kolom pertama di baris yang sama. Tetapi dalam kasus ini tidak berfungsi; CR hanya dimakan secara diam-diam.

Selanjutnya mendapatkan CR di sana agak rumit dan setidaknya di sini melibatkan editor teks. Saya sarankan Anda menulis sedikit program utilitas yang akan melakukan ini untuk Anda, sebenarnya tidak terlalu sulit. Program C kecil berikut mungkin sudah cukup (jika Anda tidak perlu Unicode):

#include <stdio.h>

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

Itu tidak lebih dari mencetak karakter CR dan kemudian teks yang Anda tentukan sebagai argumen pertama. Penggunaan sebagai berikut:

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

Baris terakhir adalah panggilan ke program itu. Baris kedua adalah idiom batch normal untuk mencetak teks tanpa jeda baris tambahan (yang penting dalam kasus ini karena jika tidak, Anda tidak dapat menimpa baris). Anda bisa menggunakan program di atas juga di tempat itu.

Cara hacky ringan, tetapi satu-satunya di mana Anda dapat yakin di mana Anda berakhir, akan digunakan clssebelum output langkah Anda. Akan berkedip tetapi dengan cara itu Anda selalu menulis ke kiri atas. Dan mengalahkan segala sesuatu yang terlihat di konsol (itulah sebabnya saya tidak akan merekomendasikannya); sebagian besar pengguna tidak terlalu menyukainya.

Joey
sumber
OK, saya curiga itu tidak mungkin dilakukan dengan baris perintah yang bersih. Jika saya ingin membuat utilitas melakukan ini, saya mungkin juga memasukkan semuanya ke dalam utilitas. Yang saya inginkan hanyalah hitungan mundur yang terlihat yang menunggu 5 detik, menghitung mundur setiap detik hingga selesai.
awe
4
kagum: Jika Anda menggunakan Vista atau yang lebih baru, maka timeout 5akan berfungsi.
Joey
Bagus! Terima kasih! batas waktu 5 berfungsi!
awe
4
Seharusnya saya memposting masalah saya yang sebenarnya pertama kali ...
awe
Tentu saja Anda bisa; tambahkan saja carriage return setelah langkah 1! Selain itu, berikut adalah beberapa kode untuk mendapatkan carriage return tanpa melibatkan editor teks:for /f %%a in ('copy /Z "%~f0" nul') do set "CR=%%a"
Zimba
1

Dapatkan karakter baris baru, tulis langkah berikutnya, kembali ke awal baris, tulis baris berikutnya:

@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.
Zimba
sumber
Ini hanya akan berfungsi jika Step 1 Step 2 Step 3semuanya memiliki panjang yang sama. Jika bukan teks yang set /ptersisa pertama . Tidak yakin bagaimana cara memperbaikinya.
Ste
Masalah itu dapat diperbaiki dengan menggunakan karakter spasi putih di prompt berikutnya. untuk menutupi karakter sebelumnya. Contoh set /p "=Step 2SPACESPACESPACESPACE!Newline!" <NUL sebagai kebalikan dari set /p "=Step 2!Newline!" <NUL. Tukar SPACEuntuk karakter.
Ste
Jika baris sebelumnya lebih panjang, tambahkan spasi untuk mengosongkan karakter tambahan, atau mundur dari akhir baris ke awal, atau cukup mundur ke karakter tambahan.
Zimba
0

Anda perlu pustaka kursor layar suka cursesatau ncurses, tapi saya tidak terlalu terbiasa dengan penggunaannya. Kedua perpustakaan dikembangkan untuk sistem Unix, tetapi Anda dapat menemukannya untuk Windows (di lingkungan Cygwin , atau GnuWin32 ).

Saya tidak tahu cara mudah untuk mengaksesnya dalam file batch bergaya DOS. Anda mungkin lebih baik pemrograman dalam bahasa yang dikompilasi. Lihatlah Ncurses HOWTO untuk mendapatkan ide yang lebih baik tentang apakah itu akan berguna.

quack quixote
sumber
kutukan cukup banyak untuk terminal dan emulator terminal saja. Mereka tidak benar-benar memetakan ke API konsol asli Windows.
Joey
TIDAK perlu perpustakaan eksternal; berfungsi dengan baik dengan alat CMD.
Zimba
0

Solusi 1

Dengan Notepad ++ , Anda dapat memasukkan Backspace ←karakter (ASCII 0x08) secara langsung, menggunakan Panel Penyisipan Kode ASCII (Edit> Panel Karakter).

Solusi saya adalah memasukkan [BS]karakter secara langsung dan kemudian, seperti solusi lain yang diposting di sini, gunakan beberapa kali untuk menghapus karakter sebelumnya:

Kode

@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

Tangkapan layar Notepad ++

Kumpulan Windows ditimpa


Keluaran

Output CMD


Solusi 2

Kemungkinan lain adalah menggunakan cecho (perintah gema dengan dukungan warna) untuk memasukkan Carriage Return ↵karakter unicode (U + 000D):

Kode

@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.exeberjalan secara signifikan lebih cepat di mesin saya daripada cecho.exe.

andronoid
sumber