バッチファイルからのコマンド出力で同じ行を上書きする方法


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

この答えは、Dave Benhamによって作成された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...

2
私にとっては、これは画面に「ステップ2」だけを表示するのではなく、「ステップ1ステップ2」を出力するだけです。
galmok

@galmokこれも私に起こるし始めているが、私は確信している(私は完全にあなたが記述動作に変更されました。最近は入れ作業に使用したスクリプトを持っているとして)それがために使用されることはありませんと思われるsetコマンドが今どんなのストリップの後のCRおよびLF文字(およびスペース)==との間に空白以外の文字を入れてみてください!ACSII_13!
timfoden '26

これをすべて行う方法があります...実際に他の人が気づいているかどうかを確認するようになりました。...スタックオーバーフローに関する回答を記述できますか?OR ..質問が好きですぐに答える?私はあなたがそれで何ができるかについて質問形式でそれを書くことができると思います。私は何かを食べに行かなければなりませんが、あなたのためのリンクでこれを更新します。
ブレントリッテンハウス

!ASCII_13!ので、ステップ2で、ストリッピング防止するためのステップ1の後にあなたがコーディングします。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か所戻り、を上書き1し、最後に完全に戻り、で上書きStep 2Endます。

これは、バックスペースである特殊なASCII文字8で後戻りします。cmdでの記述方法がわからないため、VBS Chr()関数を実行する:EVALUATE関数を使用して、バックスペース文字を変数に入れています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"

これにより、バックスペース文字がBSPACE変数に設定されます。結果を確認するには、次のように入力します。

echo ab%BSPACE%c

出力: ac

このBSPACE変数を複数回使用して、複数の文字を削除できます。

ここで、変数にキャリッジリターンを設定する場合は、

for /F "usebackq" %%a in (/ Z "%〜dpf0" nulをコピー) DO (set "cr=%%a")

結果を表示するには、次のように入力します。 setlocal EnableDelayedExpansion & echo asfasdhlfashflkashflksa!CR!***

出力は次のようになります。 ***asfasdhlfashflkashflksa

上記の@davourの回答も美しいですが、@ timfodenの回答はうまくいきませんでした。


@timfodenの回答は!前のステップの最後に移動する必要があります。また、これらすべての%BSPACE%sの代わりに、!CR!そして空白で埋めます:set /p "=.!CR!End. " <NUL&echo:
Zimba '21

3

できません。通常、このようなことは、カーソルを同じ行の最初の列に戻すファイルに復帰文字(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"

最後の行は、そのプログラムの呼び出しです。2行目は、末尾の改行なしでテキストを印刷するための通常のバッチイディオムです(それ以外の場合、行を上書きできなかったため、この場合は重要です)。ただし、上記のプログラムをその場所で使用することもできます。

少しハッキーな方法ですが、最終的にどこに行くかを確実にできる唯一の方法は、clsステップ出力の前に使用することです。ちらつきは発生しますが、常に左上に書き込みます。そして、コンソールに表示されていたものをすべて上書きします(そのため、私はそれをお勧めしません)。ほとんどのユーザーはそれをあまり好きではありません。


わかりました、私はそれがクリーンなコマンドラインで行うことが不可能であるという疑いがありました。ユーティリティにこれを行わせたい場合は、すべてをユーティリティに入れることもできます。私が本当に欲しかったのは、5秒待機して、完了するまで毎秒カウントダウンする目に見えるカウントダウンだけでした。
畏敬の念

4
畏敬の念:Vista以降を使用している場合timeout 5は機能します。
ジョーイ

すごい!ありがとうございました!タイムアウト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残ります。これを修正する方法がわかりません。
Ste

この問題は、次のプロンプトで追加の空白文字を使用することで修正できます。以前のキャラクターをカバーします。とは対照的な 。キャラクターと交換。set /p "=Step 2SPACESPACESPACESPACE!Newline!" <NULset /p "=Step 2!Newline!" <NULSPACE
サント

前の行が長い場合は、スペースを追加して余分な文字を空白にするか、行末から先頭までバックスペースするか、余分な文字までバックスペースします。
ジンバ

0

cursesまたはのような画面カーソルライブラリが必要ncursesですが、私はそれらの使用についてあまり詳しくありません。どちらのライブラリもUnixシステム用に開発されましたが、Windows(Cygwin環境、またはGnuWin32)用に見つけることができます。

DOSスタイルのバッチファイルで簡単にアクセスする方法は知りません。コンパイルされた言語でプログラミングした方がいいかもしれません。Ncurses HOWTOを調べて、それが有用かどうかをよりよく理解してください。


cursesは、端末と端末エミュレータのみにかなり対応しています。それらは実際にはWindowsのネイティブコンソールAPIにマップされません。
Joey、

外部ライブラリは必要ありません。CMDツールで正常に動作します。
ジンバ

0

解決策1

メモ帳++それが挿入することが可能ですBackspace ←その使用して、直接文字(ASCII 0x08の)をASCIIコードの挿入パネル(編集>文字パネル)。

私の解決策は、[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

もう1つの可能性は、cecho(色をサポートするechoコマンド)を使用しCarriage Return ↵て、aをUnicode文字(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

注意:cecho_x64.exe私のマシンでは、よりもかなり高速に実行されcecho.exeます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.