Update:

バッチ処理サンプル(その5)いろいろな処理パターン

バッチ処理のパターン化

Windows 2000、XPで使えるようになったバッチ引数や環境変数の拡張機能を利用して処理のパターン化を行います。
たいした処理はしていませんが、何かの参考や役に立てば幸いです。
※Windows 9x/meでは利用できません。ご了承ください。

文字列の分割(split)と抽出

●文字列の分割
文字列の置換と「FOR /F」を組み合わせて perl の「split」( phpの「explode」)もどきを考えてみます。
for /f 文の %str:,= % 部分で「,」をスペース「 」に置き換えて文字列 %str% を分割します。


@title 文字列の分割
@echo off

set str=CommandLine,Interface,コマンドライン

for /F "tokens=1-10" %%a in ('echo %str:,= %') do echo %%a %%b %%c %%d %%e %%f

exit /b

※この処理パターンは、コンマ区切りのテキストファイルを(「type」コマンドなどで)行単位で読み出して処理を行うときに利用できるでしょう。

●文字列の抽出
文字列「2013/05/05-01:23:45 www.yahoo.co.jp,www.google.co.jp,jp.msn.com」から

(1)「www.google.co.jp」を取り出します。
set w=2013/05/05-01:23:45 www.yahoo.co.jp,www.google.co.jp,jp.msn.com
set s=%w:,= %
for /f "tokens=3" %%I in ('echo %s%') do set tm=%%I

echo %tm%

(2)時刻「01:23:45」を取り出します。
set w=2013/05/05-01:23:45 www.yahoo.co.jp,www.google.co.jp,jp.msn.com
set s=%w:-= %
for /f "tokens=2" %%I in ('echo %s%') do set tm=%%I

echo %tm%

(3)日付「05/05」を取り出します。
set w=2013/05/05-01:23:45 www.yahoo.co.jp,www.google.co.jp,jp.msn.com
set s=%w:/= %
set s=%s:-= %
for /f "tokens=2-3" %%I in ('echo %s%') do set tm=%%I/%%J

echo %tm%

(4)ドメイン「google.co.jp」を取り出します。
set w=2013/05/05-01:23:45 www.yahoo.co.jp,www.google.co.jp,jp.msn.com
set s=%w:*google=google% & rem 「google」より前の文字を全部削除します。
set s=%s:/=%
set s=%s:,= %
for /f "tokens=1" %%I in ('echo %s%') do set tm=%%I

echo %tm%

(5)スペースでは分割したくない場合
文字列「C:\USER\ユーザー名\マイ ドキュメント\My Folder\batch」から
「My Folder」を取り出します。
set w=C:\USER\ユーザー名\マイ ドキュメント\My Folder\batch
set s=%w: =_sp_%
set s=%s:\= %
for /f "tokens=5" %%I in ('echo %s%') do set tm=%%I

set tm=%tm:_sp_= %
echo %tm%

以上のように、環境変数の展開とFOR /Fオプションで万能とはいいませんが、多くの文字列はパターンによる分割や置き換えが可能です。


ページトップへ戻る

バージョンチェック

Windowsのバージョンををチェックします。
インターネットでもいろいろな方法が紹介されていますが、ここでは、VERコマンドからバージョン番号を取得します。
server 2003, 2008, 2012あるいはSP(サービスパック)などの細かい区別はしていません。ご注意ください。

@title バージョンチェック
@echo off
rem verコマンドの出力を%arg%に取り出します。
for /f %%v "delims=" in ('ver') do set arg=%%v
rem Windowsのバージョンによって、%arg% に含まれる、2000、XPの文字を削除して書式を整えます。
set arg=%arg:2000 =%
set arg=%arg:XP =%

rem %arg%からバージョン番号を含む文字列を切り出します。
for /f "tokens=4" %%v in ('echo %arg%') do set arg=%%v
rem バージョン番号の上位3文字を取り出して、対応するOS名を表示します。
if %arg:~0,3% EQU 5.0 echo Windows 2000&goto skip
if %arg:~0,3% EQU 5.1 echo Windows XP&goto skip
if %arg:~0,3% EQU 6.0 echo Windows vista&goto skip
if %arg:~0,3% EQU 6.1 echo Windows 7&goto skip
if %arg:~0,3% EQU 6.2 echo Windows 8&goto skip
echo Unknown Windows version.
:skip
pause
echo on
exit /b

ページトップへ戻る


ファイルの属性による条件判断

ファイルの属性やサイズなどの条件で削除を行います。
コマンド引数のオプション機能を使って条件のチェックを行っています。

@title ファイル の 条件削除
@echo OFF
pushd %~dp0
rem 処理対象の候補となるファイル名の設定
set f=*.*

for /f %%a in ('dir /A- /B %f%') do call :check %%a

popd
pause
exit /b

rem ---------------------------------------------------------
:check
set arg=%~a1%
rem echo.
rem ファイル属性が一致するかチェック(attrib=drahs----)
rem d:ディレクトリー(フォルダー), r:読み取り専用, a:アーカイブ, h:隠し, s:システム
if "%arg:~0,1%" == "d" goto skip
if NOT "%arg:~2,1%" == "a" goto skip


rem ファイルの日付「YYYY/MM/DD」を取得します。
rem YYYY:西暦年数(半角4桁の数字), MM:月(01~12), DD:日(01~31)
for /f %%d in ('echo %~t1') do set arg=%%d
rem ファイルの日付から「/」を削除して指定の数字「YYYYMMDD」より大きいかチェック
rem if NOT %arg:/=% GTR YYYYMMDD goto skip
if NOT %arg:/=% GTR 20130401 goto skip
rem ファイルの日付から「/」を削除して指定の数字「YYYYMMDD」より小さいかチェック
rem if NOT %arg:/=% LSS YYYYMMDD goto skip
if NOT %arg:/=% LSS 20130415 goto skip

rem ファイルサイズがN[byte]以上かチェック
rem N:半角数字
rem if NOT %~z1 GEQ N goto skip
if NOT %~z1 GEQ 0 goto skip
rem ファイルサイズがM[byte]より小さいかチェック
rem if NOT %~z1 LSS M goto skip
if NOT %~z1 LSS 1000 goto skip

call :exec %1
:skip
goto :EOF

rem ---------------------------------------------------------
:exec
echo 処理対象:%1 attrb:%~a1 date:%arg% size:%~z1
rem del %1
goto :EOF

ページトップへ戻る



IPアドレスの一覧

ネットワーク関連の作業で便利そうなIPアドレスの一覧を作るバッチ処理を作ってみました。
ネットワーク関連のユーティリティには無料の便利なツールがいろいろありますが、バッチで実現できることもあるので、ツールの作成に挑戦してみるのも一興かと思います。
ここでは、ネットワークアドレスの設定には、環境変数の拡張展開やFORコマンドの/Fオプションなどを利用して、ゲートウェイのIPアドレスから作っています。
また、FORコマンドの/Lオプションを使いPINGコマンドを発行してネットワーク内のIPアドレスの一覧をファイルに記録します。
IPアドレスの一覧ファイルの作成には多少時間がかかりますが、PINGコマンドを手打ちで入力するよりは楽だと思います。
※ゲートーウェイのIPアドレスが、必ずしもネットワークアドレスに一致するとは限りません。
※場合によっては、自分のIPアドレスからネットワークアドレスを作成するほうがよいかもしれません。

@title IPアドレスのチェック
@echo off
PUSHD %~dp0
rem スクリプト名の拡張子を外して、一時ファイル用に使います。
set script=%~n0

rem ゲートウェイの表示
echo Default GateWay :
ipconfig.exe | findstr "Gateway .* [0123456789]*\.[0123456789]*\.[0123456789]*\."
rem ここからネットワークアドレスを作ります。
ipconfig.exe | findstr "Gateway .* [0123456789]*\.[0123456789]*\.[0123456789]*\." > %script%.tmp
rem デフォルトゲートウェイの行を環境変数「gw」に読み取ります。
set /p gw= < %script%.tmp
rem スペースを削除します。→「DefaultGateway.........:192.168.1.1」
set gw= %gw: =%
rem 「:」をスペースに変えます。→「DefaultGateway......... 192.168.1.1」
set gw= %gw::= %
rem ゲートウェイのIPアドレスを取得します。→「192.168.1.1」
for /f "eol=; tokens=2" %%s in ('echo %gw%') do set gw=%%s
rem IPアドレスの「.」をスペースに変えて環境変数「ip」に設定します。→「192 168 1 1」
set ip=%gw:.= %
rem ゲートウェイのIPアドレスをネットワークアドレスの上位3桁に変えます。→「192.168.1.」
for /f "eol=; tokens=1-3" %%s in ('echo %ip%') do set ip=%%s.%%t.%%u.
echo.

rem ネットワークアドレスの設定
set address=
if "%~1" == "" (
    set /p address=ネットワークアドレスを入力してください。[例 192.168.1.]:
) else (
    set address=%~1
)
if "%address%" == "" set address=%ip%

rem 一覧ファイルに日付-時刻を出力して処理を開始
echo %DATE%-%TIME% > %script%.txt

rem FORループでIPアドレスの4桁目を与えながらサブルーチンを呼び出して処理を行います。
for /L %%N in (1, 1, 254) do call :sub %%N
rem arp -a でネットワーク内のアドレステーブルを表示します。
arp -a
arp -a >> %script%.txt 2>&1
rem 一時ファイルを削除などの後始末をして処理を終了します。
del %script%.tmp
pause
POPD
echo on
exit /b

:sub
    rem 区切り行をファイルに出力します。
    echo ---------------------------------------------- >> %script%.txt
    rem PINGコマンドのアドレスを画面とファイルに出力します。
    echo ping %address%%1
    echo %address%%1 >> %script%.txt
    rem PINGコマンドの結果を一時ファイルに出力します。
    ping -n 2 -w 250 %address%%1 > %script%.tmp 2>&1
    rem 一時ファイルの結果を画面と一覧ファイルに出力します。
    find "Reply" < %script%.tmp
    find "Reply" < %script%.tmp >> %script%.txt
goto :EOF


※ネットワークの操作に便利なコマンド
 Windows7以降のOSの場合、ネットワークを操作するには「netsh」が便利です。
 [使い方]
 ・固定IPアドレスの設定
   netsh interface ipv4 set address name="インターフェース名" static address="IPアドレス" mask="サブネットマスク" gateway="ゲートウェイ"
   netsh interface ipv4 set dns name="インターフェース名" static address="221.113.139.250" register=non validate=no
   netsh interface ipv4 add dns name="インターフェース名" address="202.234.232.6" index=2 validate=no
 ・DHCP(Dynamic Host Configuration Protocol)の設定
   netsh interface ipv4 set address name="インターフェース名" dhcp
   netsh interface ipv4 set dns name="インターフェース名" dhcp
 ・無線LAN:SSID、暗号キーの設定
   netsh wlan set profile name="プロファイル名" interface="インターフェース名(wi-fi)" SSIDname="SSID" keyMaterial="キー文字列" keyType=passphrase CONNECTIONtype=ESS autoSwitch=yes ConnectionMode=auto
 ・無線LAN:指定のネットワークに接続
   netsh wlan connect name="プロファイル名" ssid="SSID" interface="インターフェース名(wi-fi)"
 ・無線LAN:指定のインターフェース名の接続を切断
   netsh wlan disconnect interface="インターフェース名(wi-fi)"
 ・無線LAN:指定のプロファイルを削除
   netsh wlan delete profile name="プロファイル名" interface="インターフェース名(wi-fi)"
 ・無線LAN:無線インターフェースの詳細を表示
   netsh wlan show interface
 ・ネットワークの状態を表示
   ipconfig /all


ページトップへ戻る


配列/ハッシュ風な環境変数の使い方

環境変数を配列やハッシュ風に使う方法を紹介します。
call set 環境変数[%引数となる環境変数%]=%%配列風環境変数[%引数となる環境変数%]%%
call set 環境変数=%%配列風環境変数[%引数となる環境変数%]%%
というパターンを使います。
【使用例】
ア.環境変数参照
 配列風の環境変数を参照するには、「call」を使って遅延展開を行います。
 call echo 曜日=%%wday[%num%]%%
 ここでは、%num% を数値に展開した後に、%wday[数字]% を再展開します。

   @title 環境変数の参照
   set wday[0]=日
   set wday[1]=月
   set wday[2]=火
   set wday[3]=水
   set wday[4]=木
   set wday[5]=金
   set wday[6]=土
   :loop
   set /p num=曜日数を入力してください。(0~6):
      if %num% LSS 0 goto :loop
      if %num% GTR 6 goto :loop
   :exit_loop
   call echo 曜日=%%wday[%num%]%%

イ.配列風環境変数への入力とデータの参照
 ifの条件判断部分「if "%n%" == "END" goto :exit_loop」は、
 if "%%num[%cnt%]%%" == "END" goto :exit_loop
 や
 call if "%%num[%cnt%]%%" == "END" goto :exit_loop
 のような形が使えないので、いったん別変数(call set n=%%num[%cnt%]%%)に置き換えて
 処理をしています。

   @title 環境変数への入力
   set /a cnt = 1
   set /a num[0] = 0
   :loop
      set /p num[%cnt%]=整数を入力してください。(0~100000, 終了=END):
      call set n=%%num[%cnt%]%%
      if "%n%" == "END" goto :exit_loop
      if "%n%" == "end" goto :exit_loop
      if %n% LSS 0 goto :loop
      if %n% GTR 100000 goto :loop
      set /a cnt += 1
      goto :loop
   :exit_loop
   set /a num[%cnt%] = 0
   for /L %%L in (1, 1, %cnt%) do call echo %%num[%%L]%%


   @title 環境変数への入力
   set /a cnt = 1
   set /a num[0] = 0
   :loop
      set /p num[%cnt%]=整数を入力してください。(0~100000, 終了=END):
      call set n=%%num[%cnt%]%%
      if "%n%" == "END" goto :exit_loop
      if "%n%" == "end" goto :exit_loop
      if %n% LSS 0 goto :loop
      if %n% GTR 100000 goto :loop
      set /a cnt += 1
      goto :loop
   :exit_loop
   set /a num[%cnt%] = 0
   for /L %%L in (1, 1, %cnt%) do call echo %%num[%%L]%%


   @title 連想配列(ハッシュ)風環境変数へのアクセス
   set /a price[カレー] = 450
   set /a price[ラーメン] = 400
   set /a price[ハンバーグ] = 500
   set /a price[牛丼] = 450
   set /a price[親子丼] = 350
   set /a s = 0
   :loop
      set /p menu=メニュー名を入力してください。[カレー,ラーメン,ハンバーグ,牛丼,親子丼]:
      call set /a s += %%price[%menu%]%%
      if "%menu%" == "終了" goto :exit_loop
      if "%menu%" == "おわり" goto :exit_loop
      goto :loop
   :exit_loop
   echo 合計:%s%


ページトップへ戻る



元のページに戻る  ページを閉じる

連絡先:お問い合わせフォーム