バッチファイルで指定の文字が何文字目か調べる(ExcelのFIND関数相当)


Y子です。
趣向を変えて、Excelと同じ機能をバッチファイルで作ってみようと思います。
今回は、「FIND」関数を考えます。

文法

FIND(検索文字列, 対象, [開始位置])

概要

ExcelのFIND関数は、指定の文字(検索文字列)が、対象文字列の何文字目かを返します。
 FIND("b", "abcde") → 2
 FIND("cd", "abcde") → 3
開始位置をずらすこともできます。
 FIND("cd", "abcde", 2) → 2

これと同じものを、バッチファイルで作ります。
確認環境:Windows 10 Home (Bld. 19042.928)

コード

find_like_excel.bat
@echo off
rem 検索文字列, 対象, [開始位置=1]
set find_text=%~1
set within_text=%~2
set start_num=%~3

rem 位置カウンタ初期化
set charpos=0
rem 文字位置カウント(サブルーチン実行)
call :find_like_excel "%find_text%" "%within_text%" "%start_num%"

rem 結果出力
if "%charpos%"=="0" (
  echo 見つかりません
) else (
  echo %charpos% 文字目
)
exit /b

rem ====サブルーチン====
rem 文字位置をカウントする
:find_like_excel
  setlocal

  rem 引数がない場合は終了する
  if "%~2"=="" (echo 引数がありません & pause & exit /b)

  rem 検索文字列, 対象, [開始位置=1]
  set find_text=%~1
  set within_text=%~2
  set start_num=%~3

  rem 開始位置の指定がない場合はデフォルト「1」
  if "%start_num%"=="" (set start_num=1)
  rem バッチファイルのデフォルトは「0」なので合わせる
  set /a start_num-=1

  rem 開始位置の調整
  call set within_text=%%within_text:~%start_num%%%

  rem 文字位置カウントのループ開始
  :label_find
  rem 位置カウンタ加算
  set /a charpos+=1

  rem 文字列がなくなったら終了
  if "%within_text%"=="" (
    set charpos=0
    goto :label_end
  )

  set length=0
  set str_tmp=%find_text%

  rem strlenループ開始
  :label_strlen
  rem 長さ加算
  set /a length+=1
  rem 1文字減らす
  set str_tmp=%str_tmp:~1%
  rem 文字列がなくなったら終了
  if not "%str_tmp%"=="" (goto :label_strlen)
  rem strlenループ終了

  rem 文字列が一致すれば終了
  call set str_tmp=%%within_text:~0,%length%%%
  if "%str_tmp%"=="%find_text%" (goto :label_end)

  rem 文字列がまだあれば、1文字減らしてループ
  set within_text=%within_text:~1%
  goto :label_find
  rem 文字位置カウントのループ終了

  :label_end
  endlocal && set charpos=%charpos%
exit /b
実行結果
> find_like_excel.bat b abcde
2 文字目

> find_like_excel.bat cd abcde
3 文字目

> find_like_excel.bat cd abcde 2
2 文字目

説明

find_like_excelサブルーチンに、処理をまとめました。
引数の「検索文字列」の文字数をカウントするために、バッチファイルで文字列長を取得するで作ったget_strlenサブルーチンの処理を内包しています。

おわりに

この関数を使って、また新しいことをしてみようと思います。

では!