LoginSignup
11
6

More than 3 years have passed since last update.

バッチファイルの生産性の低さをコードで表現してみた。

Last updated at Posted at 2017-02-02

背景

Windowsでの開発はバッチファイルよりもPowerShellを使うべし、という主張ももはや古いと感じるほど、
PowerShellの普及は順調に進んでいるのではないかと思う今日頃ごろです。

もう、.batファイルなんか書かなくてもいいよね、書かないほうがいいよね、と思ってはいるのですが、
ふと気が付くとまた新しい.batファイルを作ってたりするわけで...

ちょっとした処理だからいいや、と思いつつも何だかんだ追加の処理を書いていくうちに
10行、20行と増え、メンテが大変になり、PowerShellで書き直すという2度手間のフラグが見え透いています。

まぁ、数十行の世界なら目をつぶれるのですが、ついついバッチファイルで分岐・ループを頑張る悪習があるので、
戒めとして、バッチファイルがどれだけ生産性が低いのかをコードとして記載しておこうと思った次第です。

※この記事では普及率がそれほどまで高くならなかったVBScript、JScriptについての言及を割愛しています。

以下、文字列を反転させる処理をBash、PowerShell、バッチファイルの順で書いています。
※Bashもついでに比べてみようと思ったので掲載。

Bash

Bashで文字列を反転させる場合は、処理を書く必要もなく、コマンドで済みます。

~$ echo abcdefg | rev
gfedcba

それだと、つまらな過ぎるのであえて関数を作ってみる。

#!/bin/bash

function reverse()
{
    local -r _SOURCE=$1
    local _reversed
    for (( i=${#_SOURCE} - 1; -1 < i; i-- ))
    do
        _reversed=$_reversed${_SOURCE:$i:1}
    done
    echo $_reversed
}

実行結果

~$ . reverse.sh
~$ reverse abcdefg
gfedcba

revコマンドを使用しなくても、まぁ問題なく書けるし読める。
文字数や文字列の抽出の書き方は忘れがちになるんですけどね。

PowerShell

続きまして、PowerShell。

<#
.Synopsis
   文字列を反転させる関数
#>
function Reverse
{
    [OutputType([string])]
    Param
    (
        # 反転対象となる文字列
        [Parameter(Mandatory=$true, Position=0)]
        [string]
        $Source
    )
    $reversed=""
    ($Source.Length - 1) .. 0 | % {$reversed += $Source[$_]}
    return $reversed
}

実行結果

PS >. ".\Reverse.ps1"
PS >Reverse abcdefg
gfedcba

ちょっと、長く感じたかもしれませんが、実際に反転処理している部分だけみると、Bashよりかはシンプルかと。
ここらへんは、さすがPowerShellのパイプ。

バッチファイル

最後にバッチファイル。

@echo off

setlocal EnableDelayedExpansion
pushd %~0\..

rem ----------------------------------------
rem 文字列を反転させる
rem ----------------------------------------
set source=%~1
set reversed=
call :Length "%source%" out
set /a len=%out% - 1

for /l %%I in (%len%, -1, 0) do (
  set reversed=!reversed!!source:~%%I,1!
)

echo %reversed%
goto :EOF
endlocal

rem ----------------------------------------
rem 文字列の長さを返す関数
rem 
rem @第1引数 対象文字列
rem @戻り値 文字数
rem 
rem 使用禁止文字:!"%&'=^~|;,?
rem ----------------------------------------
:Length
setlocal
set i=0
set t=%~1
If "%t%"=="" endlocal & set %2=0 & goto :EOF
:CONTINUE
set t=%t:~1%
set /a i+=1
if not "%t%"=="" goto CONTINUE
endlocal & set %2=%i%
goto :EOF

実行結果

C\:>reverse.bat abcdefg
gfedcba

コードではLength関数みたいなものを作っていますが、
バッチファイルにはそもそも関数みたいな機能はなく、
あくまでラベル構文を利用して関数みたいなものを作っています。
ググると割とやっている人が多いので、今回はこういう感じにしました。

まとめ

バッチファイルを今までよく書いたことない方は意味不明な部分がきっと多いと思います。
わかる人でも、1から書こうとするには一苦労。
遅延環境変数の展開とか慣れてないと、とにかくややこしい。(変数参照するのに%か!で悩むとか...)
基本的な処理のコマンドやら関数が乏しいことに加え、
たとえ頑張って複雑な処理を書いてもよく使用禁止文字が出てきてしまいます。

やっぱこれを見ると、つくづくバッチファイルには限界を感じますね。

※記事全体でバッチファイルについて否定的なことしか述べてませんが、
 私自身はバッチファイルの独特過ぎる構文は割と好きです。('ω')

11
6
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
6