[Windows] コマンドプロンプトで文字列入出力のTips

2017年3月27日月曜日

Windows コマンドプロンプト

PowerShellとかありますが、なんだかんだ言ってWindowsのバッチファイルって、何気に使うと便利な場面多いですよね。
でも、Unixのシェルほど融通が効かないので困ってしまうことも多いよね。

なので、ちょっと文字列入出力について、まとめ。

リダイレクトやパイプの文字を出力する

リダイレクト(<>)やパイプ(|)の文字をechoでそのまま出力しようとしても、当然コマンドライン制御文字として判定されてしまうため、うまくいかない。

>echo foo|bar|bazz
'bar' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。


この場合は | の後ろにあるbarはパイプの後段のコマンドと認識されてしまっている。
じゃあ、" で囲って、文字列と認識させてみよう。

>echo "foo|bar|bazz"
"foo|bar|bazz"


この場合は文字列とは認識されているけど、" もそのまま出力されてしまっている。

というわけで、どうするかと言うと、エスケープ文字として^(キャレット)を使う。

>echo foo^|bar^|bazz
foo|bar|bazz


こんな感じで制御文字の前に ^ を置けば、そのまま文字として出力してくれる。

Windowsのコマンドラインを体系的に説明してる資料ってなかなか見つからないんだけど、ちょっと古いもので以下がある。

The Windows NT Command Shell

Archived content. No warranty is made as to technical accuracy.
とあるので、すでに公式資料ではないんですが...

改行のみを出力

echoで改行のみを出力しようとして、単純にechoコマンドに何も引数をつけないとエコーのON/OFF切り替えになってしまう。
こんなときはechoの直後に.(ドット)を入れることによって、改行のみを標準出力に出力することができる。 このときのポイントとしては.の前後にスペースを入れないこと。

>echo.

>

>echo.>foo

>dir foo
 ドライブ C のボリューム ラベルは OS です
 ボリューム シリアル番号は BA5C-559F です

 C:\Users\user のディレクトリ
 
2017/03/22 13:09           2 foo
               1 個のファイル               2 バイト
               0 個のファイル  111,430,828,032 バイトの空き領域


改行コードの2バイトのみがfooファイルに格納されていることが分かる。

これは普通にechoのリファレンスマニュアルに載っている。

Command-Line Reference Echo

改行なしで出力

今度は改行なしで標準出力に文字列を出力してみよう。
残念ながら、これはechoコマンドではできないみたい。

なので、setコマンドの/pオプションを使う。

>echo hello & echo world
hello
world

>

>set /p x=hello<nul & echo world
hello world

>set /p x=hello<nul& echo world
helloworld


set /pは変数に格納する値をユーザに入力してもらうためのプロンプトを表示して、標準入力から読み込むためのオプション。
このため、x変数の右側に表示するプロンプトを書いて、標準入力をnulにリダイレクトしている。
ちなみにnulはUnixの/dev/nullに相当する仮想のファイルで不要な出力をリダイレクトしたりするのに使う。

Command-Line Reference Set

この場合、入力がnulのため、変数xは設定されない。
事前にxが定義されていた場合もxの値はそのまま残っている。

>set x=abc

>echo %x%
abc

>set /p x=<nul

>echo %x%
abc

これはsetの仕様なのかな...

プロンプトは空文字にもできるので、以下のようにすればサイズ0のファイルを作ることもできる。

>set /p x=<nul>bar

>dir bar
 ドライブ C のボリューム ラベルは OS です
 ボリューム シリアル番号は BA5C-559F です

 C:\Users\user のディレクトリ
 
2017/03/22 13:19           0 bar
              1 個のファイル               0 バイト
              0 個のファイル  110,387,871,744 バイトの空き領域


単にサイズ0のファイルを作りたいのであれば、nulをファイルにコピーするという手もある。

>copy nul bar


標準出力を変数に代入

標準出力の内容を変数に代入したい、ってこともよくあると思う。
そんな場合はforを使う。
え?for?という感じだけど、forはサブシェルを実行して、その標準出力を1行ずつループ変数に格納してくれる機能があるので、それを使ってループ実行部分でループ変数の内容を外側の変数に代入する。

>for /f "delims=" %x in ('echo hello') do @set foo=%x

>echo %foo%
hello


Command-Line Reference For

Unixシェルの$()とか``に相当するけど、かなりまわりくどいというか面倒な記述になってしまうのが難点だね。