Windowsバッチ:改行なしでエコー


231

echo -n出力の最後で改行を抑制するLinuxシェルコマンドに相当するWindowsバッチは何ですか?

アイデアは、ループ内の同じ行に書き込むことです。



2
これは私をほぼ夢中にさせました..私echoは取ること-nができると知っていましたが、それではうまくいきcmd.exeません^^
パニー

11
@panny-一般的な名前にもかかわらず、echoはWindowsとPosixの間で同じコマンドではありません。nslookupと同じですが、オプションが異なります。したがって、Windowsに関する質問の文脈での「私は知っているecho可能性がある-n」というコメントは正しくありません。
user66001 2013年

回答:


236

を使用setして、/p改行なしでエコーできるパラメーター:

C:\> echo Hello World
Hello World

C:\> echo|set /p="Hello World"
Hello World
C:\>

ソース


86
パイプは、2つの追加のcmdタスクを作成するため、非常に低速です<nul set /p =Helloset /p最初の文字やスペース/タブとして等号をエコーできません。
ジェブ

11
それは私のシステム上のほぼ15倍の速さだ
ジェブ

28
「Hello World」を引用符で囲んで、dの後に余分なスペースが入らないようにしてください。
ブライアン

13
警告:これにより、ERRORLEVELが1に変更されます。@ xmechanixの回答を参照してください。
CoperNick 2014年

6
@ user246694 < nulNULデバイスからのリダイレクトです。それは何が含まれていませんが、それはのために十分であるset /pユーザーの入力を待って停止へ
ジェブ

100

使用:echo | set /p=または<NUL set /p=両方で改行を抑制します。

ただし、set /p=変数名を指定せずに設定するとERRORLEVELが1に設定されるため、ERRORLEVELのチェックが重要になるときにより高度なスクリプトを作成する場合、これは非常に危険です。

より良い方法は、次のようにダミー変数名を使用することです:
echo | set /p dummyName=Hello World

私は難しい方法を見つけなければならなかったので、これはバックグラウンドで卑劣なことをしなくてもあなたが望むものを正確に生成しますが、これはパイプバージョンでのみ機能します。<NUL set /p dummyName=Hello引き続きERRORLEVELを1に上げます。


20
警告:このコマンドはERRORLEVELを0に設定します。ERRORLEVELが0より大きい場合は、ERRORLEVELを0に変更します。これは、より高度なスクリプトを作成する場合にも危険になる可能性があります。(ただし、回答は+1)
CoperNick、2014年

したがって、基本的にIF ERRORLEVEL == 0(...)ELSE(...)は、これらの状況で環境に害を及ぼさないために必要です。シーッシュ。
SilverbackNet 2017

28

単純なSET / Pメソッドには、Windowsのバージョン間でわずかに異なる制限があります。

  • 先頭の引用符が削除される場合があります

  • 先頭の空白は削除される場合があります

  • 先行=すると構文エラーが発生します。

詳細については、http://www.dostips.com/forum/viewtopic.php?f = 3&t = 4209を参照してください

jebは、行送りなしの出力テキストでほとんどの問題を解決する巧妙な解決策を投稿しました。先頭のスペースまたは=でも、Windowsのどのバージョンでも、改行なしですべての有効なバッチ文字列を安全に印刷できるようにメソッドを調整しましたXP以降。:writeInitializeメソッドには文字列リテラルが含まれているため、サイトに適切に投稿できない場合があることに注意してください。文字シーケンスがどうあるべきかを説明する注釈が含まれています。

:writeそして:writeVar方法は面倒有数の文字を含む文字列のみがジェブのCOPYメソッドの私の修正バージョンを使用して書かれているように最適化されています。問題のない文字列は、よりシンプルで高速なSET / Pメソッドを使用して記述されます。

@echo off
setlocal disableDelayedExpansion
call :writeInitialize
call :write "=hello"
call :write " world!%$write.sub%OK!"
echo(
setlocal enableDelayedExpansion
set lf=^


set "str= hello!lf!world^!!!$write.sub!hello!lf!world"
echo(
echo str=!str!
echo(
call :write "str="
call :writeVar str
echo(
exit /b

:write  Str
::
:: Write the literal string Str to stdout without a terminating
:: carriage return or line feed. Enclosing quotes are stripped.
::
:: This routine works by calling :writeVar
::
setlocal disableDelayedExpansion
set "str=%~1"
call :writeVar str
exit /b


:writeVar  StrVar
::
:: Writes the value of variable StrVar to stdout without a terminating
:: carriage return or line feed.
::
:: The routine relies on variables defined by :writeInitialize. If the
:: variables are not yet defined, then it calls :writeInitialize to
:: temporarily define them. Performance can be improved by explicitly
:: calling :writeInitialize once before the first call to :writeVar
::
if not defined %~1 exit /b
setlocal enableDelayedExpansion
if not defined $write.sub call :writeInitialize
set $write.special=1
if "!%~1:~0,1!" equ "^!" set "$write.special="
for /f delims^=^ eol^= %%A in ("!%~1:~0,1!") do (
  if "%%A" neq "=" if "!$write.problemChars:%%A=!" equ "!$write.problemChars!" set "$write.special="
)
if not defined $write.special (
  <nul set /p "=!%~1!"
  exit /b
)
>"%$write.temp%_1.txt" (echo !str!!$write.sub!)
copy "%$write.temp%_1.txt" /a "%$write.temp%_2.txt" /b >nul
type "%$write.temp%_2.txt"
del "%$write.temp%_1.txt" "%$write.temp%_2.txt"
set "str2=!str:*%$write.sub%=%$write.sub%!"
if "!str2!" neq "!str!" <nul set /p "=!str2!"
exit /b


:writeInitialize
::
:: Defines 3 variables needed by the :write and :writeVar routines
::
::   $write.temp - specifies a base path for temporary files
::
::   $write.sub  - contains the SUB character, also known as <CTRL-Z> or 0x1A
::
::   $write.problemChars - list of characters that cause problems for SET /P
::      <carriageReturn> <formFeed> <space> <tab> <0xFF> <equal> <quote>
::      Note that <lineFeed> and <equal> also causes problems, but are handled elsewhere
::
set "$write.temp=%temp%\writeTemp%random%"
copy nul "%$write.temp%.txt" /a >nul
for /f "usebackq" %%A in ("%$write.temp%.txt") do set "$write.sub=%%A"
del "%$write.temp%.txt"
for /f %%A in ('copy /z "%~f0" nul') do for /f %%B in ('cls') do (
  set "$write.problemChars=%%A%%B    ""
  REM the characters after %%B above should be <space> <tab> <0xFF>
)
exit /b

1
すべてのキャラクターを処理できる非常に強力なソリューションを見るのはいいことです
jeb

2
コンピューターがたまたまインターネットにネットワーク接続している場合、大体これだけのバッチコードを使用して、コンピューターにpythonまたはその他のバッチをダウンロードおよびインストールできる何かをダウンロードしてインストールできることを指摘しておきます。バッチは楽しいですが、文字列機能は週末の挑戦に最適です。
n611x007 2015

@dbenhamの6行目の "echo("は、機能的には "echo。"と同じです。以前には見られませんでした。)
Skip R

2
@SkipRは-はい、それは機能的に同じであるECHO.以外ECHO.曖昧な状況下で失敗する可能性があり。あいまいな状況でも失敗する可能性のある他の形式がたくさんあります。常に機能するのはだけですECHO(
dbenham 2018

10

@xmechanixの回答の補足として、内容をファイルに書き込んでいることに気付きました。

echo | set /p dummyName=Hello World > somefile.txt

これにより、出力された文字列の最後に余分なスペースが追加されます。これは、文字列の最後に新しい行(別の空白文字)を追加しないようにするため、特に不便です。

幸いなことに、印刷する文字列を引用します。つまり、次のようにします。

echo | set /p dummyName="Hello World" > somefile.txt

末尾に改行や空白文字なしで文字列を印刷します。


5
あなたが間にスペースを入れていない場合は、余分なスペースが消えなければならないWorld>...
aschipfl

@aschipfl試してみましたが、しませんでした。
Joan Bruguera 2016

文書化されていないsetコマンドの機能である引用変数メソッドは、Windows NTのすべてのバージョン(および覚えている場合は9x)で機能するため、一般的にはアプローチする方法がわかります。つまり、変数名を値の最後に引用符で囲みます。これはSet / Pにも当てはまります。
Ben Personick 2017年

1
IE:エコー| set / p "dummyName = Hello World"> somefile.txt
Ben Personick

2
@aschipfl引用符を使用せず、パイプを使用すると、余分なスペースが表示されます。XXDは、私たちが例えば参照して進ダンプユーティリティで set /p="abc"<nul|xxd -p表示され616263 、一方、 set /p=abc<nul|xxd -p与え61626320
barlop

9

SET / Pで取り除かれた空白の解決策:

トリックは、テキストエディターEDIT for DOSで呼び出すことができるバックスペース文字です。EDITで作成するには、ctrlP + ctrlHを押します。ここに貼り付けますが、このウェブページでは表示できません。ただし、メモ帳には表示されます(中央に白い円がある小さな黒い四角形のように奇妙です)

だからあなたはこれを書く:

<nul set /p=.9    Hello everyone

ドットは任意の文字にすることができます。テキストがそこから始まり、スペースの前にあり、「Hello」ではないことをSET / Pに伝えるためだけです。「9」は、ここに表示できないバックスペース文字の表現です。あなたは9の代わりにそれを置く必要があります、そしてそれは「」を削除します、その後これを得るでしょう:

    Hello Everyone

の代わりに:

Hello Everyone

それが役に立てば幸い


2
Windows 7で機能することを忘れてしまいました。コマンドラインでは機能せず、バッチでのみ機能します。charを取得していない場合は、この例をダウンロードしてください:pecm.com.sapo.pt/SET_with_backspace_char.txt
Pedro

エコーにも当てはまります
ベンペルソニック2017年

...それで、かなり気の利いた徹底的な検索を行った後、私はこれがネット上のどこにも見つかりませんでした。それは私が実際に何かを発見したのは初めてのことかもしれません。知らない人のために、cmdプロンプトをレガシーモードにして正しいフォントを使用すれば、制御文字を入力できます。...しかし、何かをファイルまたはconにリダイレクトするだけでも機能します。真剣に。これを正確にコマンドプロンプトに貼り付けます: "echo←c◙◙○○Harharhar !!◙○○-------------◙◙○○私は最悪です!?: '(○♪ !○NOPEは•♪○私は偉大なHazzahルOOPを感じる◙◙○私はprogrammeer私を聞くのです...something.◙>詐欺」!。
ブレントリッテンハウス

さて、私は他の誰よりも早くこれを見つけたことを願っていますが...これは、Unicodeコードページにないことに依存しているようです。chcp 437の変数に最初の1つを保存し、セットを変数に設定するか、出力してから、元に戻すことができます(それでも出力されるはずです)。私はまだそれで遊んでいます。
ブレントリッテンハウス

また、←cが画面をクリアする理由を誰かが知っていますか?!そのインスタンスはネット上のどこにも見つかりません。2つの文字の間に空白を入れることができるように見えますが、具体的にはその組み合わせです。その他の文字については、最初の文字を削除するだけです。
わかり

7

gnuwin32から「tr」を使用して改行を削除できます(coreutilsパッケージ)。

@echo off
set L=First line
echo %L% | tr -d "\r\n"
echo Second line
pause

ちなみに、大量のスクリプトを作成している場合、gnuwin32は金鉱です。


git bashのインストールもお勧めします。それがgnuwin32と同じではないことを確認してください(そして、それは金鉱であるため、+ 1です)、それはちょうど良い設定であり、スタートメニューボタンを含むほぼすべての場所でマウスの右ボタンにgit-bashがあります。
ハクレ2013年

のように、最後のスペース文字を削除するためにtrを使用できますtrimか?
パニー

sedをトリムに使用:sed -e "s / * $ //"
BearCode

@panny-trimというposix / linuxユーティリティが見つかりません。また、\r\nまたは\r\n(それぞれOSX、POSIXとWindowsで新線)は、「スペース」文字ではありません。
user66001 2013年

5

ここに別の方法があります、それは-NoNewLineパラメーターを持つPowershell Write-Hostを使用し、それを start /b、バッチから同じ機能を提供します。

NoNewLines.cmd

@ECHO OFF
start /b /wait powershell.exe -command "Write-Host -NoNewLine 'Result 1 - ';Write-Host -NoNewLine 'Result 2 - ';Write-Host -NoNewLine 'Result 3 - '"
PAUSE

出力

Result 1 - Result 2 - Result 3 - Press any key to continue . . .

以下の1つは少し異なり、OPが望むようには機能しませんが、各結果がカウンターをエミュレートする以前の結果を上書きするため興味深いものです。

@ECHO OFF
start /b /wait powershell.exe -command "Write-Host -NoNewLine 'Result 1 - '"
start /b /wait powershell.exe -command "Write-Host -NoNewLine 'Result 2 - '"
start /b /wait powershell.exe -command "Write-Host -NoNewLine 'Result 3 - '"
start /b /wait powershell.exe -command "Write-Host -NoNewLine 'Result 4 - '"
start /b /wait powershell.exe -command "Write-Host -NoNewLine 'Result 5 - '"
start /b /wait powershell.exe -command "Write-Host -NoNewLine 'Result 6 - '"
start /b /wait powershell.exe -command "Write-Host -NoNewLine 'Result 7 - '"
start /b /wait powershell.exe -command "Write-Host -NoNewLine 'Result 8 - '"
start /b /wait powershell.exe -command "Write-Host -NoNewLine 'Result 9 - '"
PAUSE


2

多分これはあなたが探しているものです、それは古い学校のスクリプトです...:P

set nl=^& echo. 
echo %nl%The%nl%new%nl%line%nl%is%nl%not%nl%apparent%nl%throughout%nl%text%nl%
echo only in prompt.
pause

または、新しい行に書き込むのではなく、現在の行を置き換えようとしていますか?「。」の後にある「%bs%」を削除することで、これを試すことができます。署名し、「メッセージ例」の後に他の「%bs%」を空ける。

for /f %%a in ('"prompt $H&for %%b in (1) do rem"') do set "bs=%%a"
<nul set /p=.%bs%         Example message         %bs%
pause

変数が意図されている以外の目的で使用されているため、これは本当に興味深いと思います。ご覧のとおり、「%bs%」はバックスペースを表します。2番目の「%bs%」は、バックスペースを使用して「サンプルメッセージ」の後にスペースを追加し、「サンプルメッセージ」の後に実際に表示文字を追加せずに「一時停止コマンドの出力」を区切ります。ただし、これは通常のパーセント記号でも可能です。


2
私はset nl=^& echo.いたるところでこのトリックを目にし、変数の名前は誤解を招くものです。%NL%でありません改行文字:それがために展開する&echo.ので、最後に、あなたが新しい実行しているechoコマンドを毎回、それゆえ改行。あなたはそれを書いてチェックアウトすることができecho "%nl%The%nl%new%nl%line%nl%is%nl%not%nl%apparent%nl%throughout%nl%text%nl%"ます。あなたは"& echo. The& echo. new& echo. line& echo. is& echo. not& echo. apparent& echo. throughout& echo. text& echo. "、トリックを明らかにします。出力は同じですが、提案した理由ではありません。
cdlvcdlv 2018

2

DIY cw.exe(コンソール書き込み)ユーティリティ

箱から出してすぐに見つけられない場合は、DIYできます。これとともにcwユーティリティを使用すると、あらゆる種類の文字を使用できます。少なくともそう考えたいです。それをストレステストして教えてください。

ツール

必要なのは.NETだけですインストールされている。これは、今日では非常に一般的です。

材料

入力/コピー貼り付けされた一部の文字。

手順

  1. .bat次の内容のファイルを作成します。
/* >nul 2>&1

@echo off
setlocal

set exe=cw
for /f "tokens=* delims=" %%v in ('dir /b /s /a:-d  /o:-n "%SystemRoot%\Microsoft.NET\Framework\*csc.exe"') do set "csc=%%v"

"%csc%" -nologo -out:"%exe%.exe" "%~f0"

endlocal
exit /b %errorlevel%

*/

using System;

namespace cw {
    class Program {
        static void Main() {
            var exe = Environment.GetCommandLineArgs()[0];
            var rawCmd = Environment.CommandLine;
            var line = rawCmd.Remove(rawCmd.IndexOf(exe),exe.Length).TrimStart('"');
            line = line.Length < 2 ? "\r" : line.Substring(2) ;
            Console.Write(line);
        }
    }
}
  1. それを実行します。

  2. これで4KBのユーティリティができたので、を削除できます.bat

または、このコードをバッチとしてサブルーチンとして挿入し、結果.exe%temp%に送信してバッチで使用し、完了したら削除することもできます。

使い方

改行なしで何かを書きたい場合:
cw Whatever you want, even with "", but remember to escape ^|, ^^, ^&, etc. unless double-quoted, like in "| ^ &".

キャリッジリターン(行の先頭に移動)が必要な場合は、
cw

したがって、コマンドラインからこれを試してください:

for /l %a in (1,1,1000) do @(cw ^|&cw&cw /&cw&cw -&cw&cw \&cw)

私はあなたの答えに触発され、作成されたこのゴーと小さなツールと、この Azureのパイプラインのために付随する作業を。パイプで渡されるstdoutを取得し、ビルドで取得される特定の形式で出力します。ありがとうございました!
riezebosch

2

@arnepのアイデアから関数を作成しました。

echo | set / p = "Hello World"

ここにあります:

:SL (sameline)
echo|set /p=%1
exit /b

でそれを使用するcall :SL "Hello There"
私は、これは何も特別なことを知っているが、それは私が、私はここに掲載したい考え出し、それを考えるとそう長く連れて行ってくれました。


1

サンプル1:これは機能し、終了コード= 0を生成します。これで問題ありません。「。」に注意してください 、エコーの直後。

C:\ Users \ phife.dog \ gitrepos \ 1 \ repo_abc \ scripts#@echo
。| set / p JUNK_VAR =これはLinuxのように表示されるメッセージですecho -nはそれを表示します...&echo%ERRORLEVEL%

これは、Linux echo -nが表示するようなメッセージです... 0

サンプル2:これは機能します、終了コード= 1を生成します。それは悪いことです。エコー後の「。」の欠落に注意してください。それが違いのようです。

C:\ Users \ phife.dog \ gitrepos \ 1 \ repo_abc \ scripts#@echo
| set / p JUNK_VAR =これはLinuxのように表示されるメッセージですecho -nはそれを表示します...&echo%ERRORLEVEL%

これは、Linux echo -nが表示するように表示されるメッセージです... 1


1

この質問への回答に触発されて、進行状況の値(0〜100%)を同じ行に出力し続ける(前の行を上書きする)単純なカウンターバッチスクリプトを作成しました。たぶん、これは同様の解決策を探している他の人にとっても価値があるでしょう。

備考*は印刷できない文字です。これらは文字である[ Alt+ Numpad 0+ Numpad 8]キーの組み合わせを使用して入力する必要がありbackspaceます。

@ECHO OFF

FOR /L %%A in (0, 10, 100) DO (     
    ECHO|SET /P="****%%A%%"    
    CALL:Wait 1
)

GOTO:EOF

:Wait
SET /A "delay=%~1+1"
CALL PING 127.0.0.1 -n %delay% > NUL
GOTO:EOF

0

そのような選択肢はないと思います。あるいは、これを試すことができます

set text=Hello
set text=%text% world
echo %text%

3
これでも改行は印刷されます。
ルネNyffenegger

3
同じ変数を必要なだけ連結して、最後にのみエコーできます。
m0skit0 2011

2
ループを実行するとき、または最後に印刷することは、データが保持されているかどうかには関係ありません。ループごとにデータを連結し、ループが終了したら印刷します。結果は同じです。
m0skit0

9
それループの進行の指標であるかどうか重要です。
gregseth 2011

3
あなたはあなたの質問でそのことを述べたり、あなたの質問のどこかにこの振る舞いを要求したことはありません。
m0skit0

0

set / pコマンドを使用すると、改行を抑制できます。set / pコマンドはスペースを認識しません。そのため、ドットとバックスペース文字を使用してスペースを認識できます。変数をメモリとして使用し、印刷したいものを保存して、文の代わりに変数を印刷することもできます。例えば:

@echo off
setlocal enabledelayedexpansion
for /f %%a in ('"prompt $H & for %%b in (1) do rem"') do (set "bs=%%a")
cls
set "var=Hello World! :)"
set "x=0"

:loop
set "display=!var:~%x%,1!"
<nul set /p "print=.%bs%%display%"
ping -n 1 localhost >nul
set /a "x=%x% + 1"
if "!var:~%x%,1!" == "" goto end
goto loop

:end
echo.
pause
exit

このようにして、改行なしで何でも印刷できます。文字を1つずつ印刷するプログラムを作ってみましたが、ループを変えることで文字の代わりに単語も使えます。

上記の例では、「enabledelayedexpansion」を使用したので、set / pコマンドは「!」を認識しません。文字の代わりにドットを印刷します。感嘆符「!」を使用しないでください。;)


-1

ここでは遅い答えですが、dbenhamの答えが約80行と長すぎ、単一の行に特殊文字を書き込む必要があり、そのスクリプトが(おそらくユーザー入力が原因で)壊れる可能性があるためset /p、おそらく、.batまたは.cmdをコンパイル済みのC ++またはC言語の実行可能ファイルとペアにしてから、coutまたはprintf文字だけをペアにするのが最も簡単です。これにより、OPのように、プログレスバーなどの文字を使用して何かを表示している場合でも、1行に複数回簡単に書き込むことができます。


@jiggunjerよろしいですか?printfWin-7 cmdペインからingを"'printf' is not recognized as an internal or external command, operable program or batch file."
取得

printfウィンドウにネイティブではありません。これはWindowsの質問です。
kayleeFrye_onDeck

1
@kayleeFrye_onDeck私はあなたのコメントが私ではなくjiggunjerに向けられていると思います。私の質問では、CおよびC ++が、フォーマットが重要な場合に、シェルコマンドのかなりプラットフォームに依存しない代替手段として使用される可能性があることを示唆しています。
SeldomNeedy 2016

1
私はすくい取ったので、父を許してください。
kayleeFrye_onDeck 2016

ただし、シェルへの入力は正しく解析する必要があります。たとえば、そのようなプログラムはどのように引用符を印刷しますか?
Alex
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.