バッチでのゴルフのヒント


14

Windows Batch(CMD)は、おそらくコードゴルフに最適な言語ではありません。

改行文字を避けてください。文字とは対照的に、バイト単位の最短コードを探している場合は、不要なキャリッジリターン(改行文字= 2バイト)をすべて削除する必要があります。&操作を使用してこれを行うことができ、コマンドごとに1バイトをトリミングします。

echo Hello&echo World.

変数の設定。スイッチを使用して変数を設定する場合、setパーサーはスペースを無視します。

set /a a+=1
set /p b="User Input: "
:: Will be handled the same as..
set/aa+=1
set/pb="User Input: "

同じパーサールールがすべてのコマンドに適用されるわけではないことに注意してください。たとえば、forループにはスペースが必要です。set, string, or command(括弧内にあるもの)とwordの間を除きdoます。

for /f %%a in (file.txt)do ...

簡単な数式。また、set /aコマンドでインクリメントに使用した式に注目してください。単純な数式の場合+= -= *= /=は、(たとえば)の代わりに使用しますset /a a=%a%+1

コマンド出力の収集。コマンドの出力を取得するには、ファイルの出力と読み取りが役立つ場合があります。そうでない場合は、forループを使用して出力を収集します。

for /f %%a in ('echo test') do set a=%%a
:: Can be shortened to
echo test>f&set/pa=<f

echo testf、というファイルにstdoutを送信し>f、新しいコマンド&を開始して、変数のファイルの内容を取得しますset/pa=<f。明らかに、これは常に役立つとは限りません。ただし、必要なのは1行の出力だけである場合もあります。

コマンド出力。コマンド出力を抑制するとき@は、コマンドの前に使用します。ただし、9個を超えるコマンドを抑制する必要がある場合@echo offは、スクリプトの先頭で使用してください。@echo offは9バイトの長さであるため、通常は長いスクリプトでより多くのバイトを節約できます。

コマンドは、単に明らかなこと以上のことを行うことがよくあります。コマンドが何をしているかを考えてください。例えば; 変数を設定し、別の変数をエコーする必要がある場合:

set a=OUTPUT
echo %a%
echo test>f
set /p b=<f

/pスイッチでsetコマンドを使用して出力%a%できます。

set a=OUTPUT
echo test>f
set /p b=%a%<f

完全にゴルフ...

set a=OUTPUT&echo test>f&set/pb=%a%<f

expamplesのカップル- すべての数字の合計を数える - ゴールドバッハの推測を

他のヒントはありがたいです-他に何か考えたらこれを更新し続けます。


16
質問の一部としてではなく、回答としてこの回答部分を投稿してください。
チャールズではないチャールズ14

@Charlesこれをどうやってやったかは、「ヒントの質問」に受け入れられる形式だと確信しています。他の人は自分のヒントで答えを追加できます。
unclemeat 14

回答:


4

カウンター

開始するカウンターとして機能する変数がある場合はいつでも0書きたいかもしれません

set count=0
set/acount+=1

; ただし、set/a設定されていない変数で使用される場合は常にその値が0

set/acounter+=1

コードブロック

コードのブロックを使用する必要があるときに、数バイトを削るにはいくつかの方法があります。

コードブロックを開くたびに、そのブロックのコードの最初の行の前に改行を挿入する必要はありません。閉じ括弧も、それ自体の行にある必要はありません。

If %a%==%b% (
     echo true
) else (
    echo false
)

にゴルフすることができます

If %a%==%b% (echo true)else (echo false)

改行なしで印刷する

これの一般的なパターンは

echo|set/p=text

しかし、あなたはに変更echoする2バイトを保存することができますcd

cd|set/p=text

2
@ ankp-morporkちょっと、ちょっと遅れました。しかし、if声明はさらにゴルフにかけることができることをお知らせしたいと思います。最適なものは次のとおりです。if %a%==%b% (echo true)else echo false
stevefestl

3

アンパサンド

&はコードを短く見せますが、使用する行が少ないため、改行と同じ数の文字を使用します。この意味は

echo a&echo b

限り

echo a
echo b

そのため、文字を無駄にせずにコードを読みやすくすることができます。

一部のテキストエディタでは、新しい行ごとに改行と改行を組み合わせるため、例外が発生する場合があります。


使用するすべてのテキストエディターで改行が2バイトをカウントするため、これを元の投稿に含めました。この説明を追加していただきありがとうございます。
unclemeat 14年

2
ウィンドウのキャリージリターンラインフィードは2文字であり、多くのテキストエディターは2文字としてカウントしますが、ゴルフの質問に最初に答え始めたとき、PPCGでは行末は常に1文字としてカウントされるというコメントがありました。
ジェリージェレミア

2
Unixスタイルの改行は、少なくとも最近のバージョンのWindowsでは、CMDスクリプトで問題なく動作します。
user2428118

1
実際には、CMDはさらに解析する前にCR文字を削除します。stackoverflow.com/questions/4094699/...
schnaader

3

数値計算の結果を直接印刷する

チャレンジで計算が必要な数値を出力する必要がある場合cmd/c set/aは、計算を保存してエコーする代わりに、計算の結果を直接出力するために使用できます。例:

@set/a a=%1+%2
@echo %a%

になる

@cmd/cset/a%1+%2

編集:どうやらスペースがまったく必要ないようで、さらに2バイト節約できます。


2

遅延拡張

長いものsetLocal enableDelayedExpansionを使用する代わりに、遅延変数展開を有効にして新しいインタープリターを開始するcmd /v on(またはcmd/von)を使用できます。

まだこれを実装していないので、例はありませんが、これを/cスイッチと組み合わせて使用​​できます。例:

@cmd/von/cset test=test^&echo !test!

アンパサンドの前にカラットが使用されていることに注意してください。複数のアンパサンドまたはその他の特殊文字を使用する必要がある場合は、/c切り替え後のすべてを引用符で囲むことをお勧めします。

@cmd/von/c"set test=test&set test1=test1&echo !test! !test1!"

この方法には、すべての入力@をマスクするために1 文字を使用するだけでよいという利点もあるため、を使用せずに(または複数の記号)の代替として使用できます。/von@echo off@

9文字:@echo off
6文字:@cmd/c

1行で実行できないより長いスクリプトの場合、次の操作を実行してバイトを節約できます。

@!! 2>nul||cmd/q/v/c%0&&exit/b

または、無制限:

@!! 2>nul || cmd /q /v on /c %0 && exit/b

@echo off&setLocal enableDelayedExpansion上記に置き換えます。

初めてスクリプト!!を実行すると、スクリプトはまったく展開されないため"!!"、コマンドではないためエラーが発生します。その後、エラー出力はnul(2>nul)にパイプされます。この最初の「コマンド」が失敗すると(||)、cmdの新しいインスタンスを呼び出し、バッチファイル自体を呼び出します(/v (on)遅延展開を有効にし、/qエコーをオフにするために使用します)。そして、!!何の変数と呼ばれるがないので、何にも拡大していきます<NULL>。その後、スクリプトの残りの部分が実行されます。その後、cmdの元のインスタンスに戻り、(&&/bウィンドウを開いたままにする条件で終了します(終了すると、最初のcmdインスタンスのコンテキストで、echoを使用してスクリプトの実行が継続されないようになります)オンおよび遅延拡張オフ)。


このため、を使用してバッチファイルを実行する場合はcmd /q /v on /c <filename>、2バイトとしてカウントする必要があり-pIます。これは、Perlフラグと同様の2つの「フラグ」であり、余分な2バイトとしてカウントされるためです。
アーティア

1

繰り返し文字列

変数に繰り返しコードブロックを設定します。変数の設定に使用されるバイト数+変数を出力するバイト数は、コードを直接呼び出すためのバイト数よりも少なくなります。

例については、以下を参照してください。合計100までの組み合わせを描く

を含む変数(「s」などの1文字の名前)を作成すると、setコマンドの使用ごとに1バイトを節約できますset<space>。これは、setコマンドを12回以上使用した場合にのみ値を生成します。(文字列の最後に文字があることに注意してくださいset s=set)。

set s=set 
%s%a=1
%s%b=2
%s%c=3
%s%d=4
%s%e=5
%s%f=6
%s%g=7
%s%h=8
%s%i=9
%s%j=10
%s%k=11
%s%l=12
%s%m=13

上記は1バイトより短いです。

set a=1
set b=2
set c=3
set d=4
set e=5
set f=6
set g=7
set h=8
set i=9
set j=10
set k=11
set l=12
set m=13

これはおそらくかなり貧しい例です-しかし、それはポイントを取得します。


1

文字列の始まり

表記法%var:~start,end%は、変数の部分文字列を抽出しますvar。ただしstartである0、あなたはそれを完全に省略することができます。,end残りの文字列が必要な場合は省略できることを既に知っています。これは、が空の場合に返されることを除いて%var:~%、のほとんど役に立たない同義語に%var%なります。(おそらく、テストで使用できます:?)~%var%if %var:~%==~


私はあなたの最後の文が私たちにこれがいくつかの引用を節約することを思い出させるのが好きです:)そのための+1。
-stevefestl

1

短縮IF EQUステートメント

if %a% equ %b% do_something
if %a%==%b% do_something

==代わりに equ を使用すると、3バイト節約されます。


IF文の引用を短くする

これは、従来のいわゆる「より安全な」if比較です。

if "%a%"=="%b%" do_something

このステートメントを短縮するには、入力が英数字のみ/ 空にできる場合に以下を実行します。

if %a%.==%b%. do_something

合計2バイトを保存します。


出力が必要な課題

質問に次のようなものがある場合:

少なくとも1つの可視文字を出力します。

あなたはこれを行うことができます:

cd

cdは、現在のディレクトリが表示されSTDOUTます。


GOTOラベルを付ける

gotoラベルをバイトで降順に並べるいくつかの方法を次に示します。

goto :l
goto l
goto:l

上記の方法は1バイトを節約します。


1
また、あなたは行うことができgoto:l、同じ1つのバイトを保存すると、そのままあなたのコロンを保つことの追加ボーナスを持っている
マテウスAvellar

私はあなたのコメントに応じてコンテンツを追加しました:@MatheusAvellar
stevefestl

1

コマンドとパラメーターの間のスペースをスラッシュで省略する

情報に欠けるタイトルについては申し訳ありません。私が取得しようとしているのは、一部の(すべてではない)Windowsコマンドでは、そのパラメータがスラッシュで始まる限り、コマンド/プログラム名とパラメータの間のスペースを省略できることです。例えば:

for /f %%G in ...

になる

for/f %%G in ...

-1バイト!

ERRORLEVELを使用する代わりに出力を配管する

ERRORLEVELを使用して、コマンドが正しく実行されたかどうかを判断するのは、最短または最も洗練された方法ではありません。代わりに、出力をパイプできます。これは次のように機能します(&&演算子の後のコマンドは、実行前のコマンドが&&エラーなしで実行された場合にのみ実行されることに注意してください。||一方で、演算子の後のコマンドは、 :

net session>nul
if %errorlevel%==0 (echo 1) else (echo 0)

これは次のものに置き換えることができます。

net session>nul&&echo 1||echo 0

-26バイト、すごい!これはchoice、ERRORLEVELが何らかの入力に従って特別な値を持っているなどのコマンドでは機能しないことに注意してください。

よろしく、
ゲイブ


1

括弧を効果的に使用する

また会ったね、

2番目の回答を投稿してすみませんが、この回答に値すると感じました。C:\Windows\System32>echo foo各コマンドの前に厄介な行を表示せずに、コマンド出力を表示するために、次のいずれかの方法を使用することが多いことに気づきました。
最初の方法(を使用echo off):

@echo off
echo foo
echo bar
echo foobar
echo barfoo

2番目の方法:

@echo foo
@echo bar
@echo foobar
@echo barfoo

ただし、これらの方法はどちらも次のような短いものではありません。

@(echo foo
echo bar
echo foobar
echo barfoo)

かなり便利ですよね?別の注意として、これは複数行の出力をファイルまたはデバイスに簡単にパイプするために使用できます。たとえば、この長いコード:

echo foo>file.txt
echo bar>file.txt
echo foobar>file.txt
echo barfoo>file.txt

大幅に短くなります:

(echo foo
echo bar
echo foobar
echo barfoo)>file.txt

このかなり長い答えを読んでくれてありがとう、そしてこれがあなたのお役に立てば幸いです。よろしく、
ゲイブ


ヒントの質問に複数の回答を投稿するのは悪くありません。
エリックアウトゴルファー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.