web-dev-qa-db-ja.com

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

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

そのアイデアは、ループの内側で同じ行に書くことです。

195
gregseth

setおよび/pパラメータを使用すると、改行なしでエコーできます。

C:\> echo Hello World
Hello World

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

出典

205
arnep

echo | set /p=または<NUL set /p=を使用すると、改行を抑制するように機能します。

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

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

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

87
xmechanix

単純なSET/Pメソッドには、Windowsのバージョンによって若干異なる制限があります。

  • 先行引用符は削除することができます

  • 先頭の空白は削除される可能性があります

  • 先頭の=は構文エラーを引き起こします。

詳しくは http://www.dostips.com/forum/viewtopic.php?f=3&t=4209 をご覧ください。

jebは、ほとんどの問題を解決する賢い解決法を 先頭にスペースや=があっても、改行なしでテキストを出力する 新しいなしで安全に有効なバッチ文字列を安全に印刷できるようにメソッドを改良した。 XP以降のすべてのバージョンのWindowsで:writeInitializeメソッドには、サイトに適切に投稿できない可能性がある文字列リテラルが含まれています。文字シーケンスがどうあるべきかを説明するコメントが含まれています。

:write:writeVarメソッドは最適化されているので、私の修正したバージョンのjebの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
26
dbenham

SET/P:で削除された空白の解決策

その裏技は、テキストエディタEDITでDOSに呼び出せる文字です。 EDITで作成するには、ctrlP + ctrlHを押します。ここに貼り付けますが、このWebページでは表示できません。それはメモ帳に表示されます(それは中央に白い円を持つ小さな黒い四角形のように、心配です)

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

<nul set /p=.9    Hello everyone

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

    Hello Everyone

の代わりに:

Hello Everyone

私はそれが役立つことを願っています

9
Pedro

@ xmechanixの答えへの補足として、私は内容をファイルに書き込むことを通して気づいた:

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

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

幸いなことに、印刷する文字列を引用符で囲みます。つまり、

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

最後に改行やスペースを入れずに文字列を印刷します。

8
Joan Bruguera

Gnuwin32から "tr"を使って改行を削除することができます( coreutils package)

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

ところで、たくさんのスクリプトを書いているのなら、gnuwin32が一番です。

7
BearCode

これは別の方法です。-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
5
Knuckle-Dragger

から ここ

<nul set /p =Testing testing

また、スペースを使用してエコーを繰り返す

echo.Message goes here

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. .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)
2
cdlvcdlv

多分これはあなたが探しているものです、それは古い学校のスクリプトです...: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%"は、 "Example message"の後に実際に目に見える文字を追加することなく "Pauseコマンドの出力"を区切るために "Example message"の後にスペースを追加するためにバックスペースを使用します。ただし、これは通常のパーセント記号でも可能です。

2
zask

@arnepの考えから関数を作りました。

echo | set/p = "Hello World"

ここでは:

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

call :SL "Hello There"と一緒に使用してください
これは特別なことではないことを私は知っていますが、それを考えるのに長い時間がかかったので、ここに投稿します。

2
Mark Deven

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

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

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

サンプル2:これは動作しますしかしは終了コード= 1を生成します。それは悪いです。エコーの後に "。"がないことに注意してください。それが違いのようです。

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

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

1
user3175529

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

0
SeldomNeedy

そのような選択肢はないと思います。代わりにこれを試すことができます

set text=Hello
set text=%text% world
echo %text%
0
m0skit0

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

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

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