Home / Windows:バッチファイル - 文字列処理

【注意!】
以下、幾つかサンプルを書いているが、パイプ記号やリダイレクト記号等を含む場合は考慮していない。悪しからず m(_ _)m

文字列操作(部分文字列)

substr/mid もどき。

%var:~offset,len% ... offset から len 文字数を得る。

第2引数は省略出来、そうすると残り全てと見做される。
第1引数の省略は説明されていないが、やってみると省略出来るようである。
何れかの引数に負を与えた場合、ちょっと変わっていて、説明は次の通り。

オフセットまたは長さのどちらかが負の値の場合、環境変数の値の長さに指定されたオフセットまたは長さを足してその数を使います。

right もどき。

%var:~-offset% ... 末尾の offset 文字数だけ

left の変形もどき。

%var:~0,-len% .... len だけ短い文字数を先頭から

負の値を使った例(文字列 "Python"):

 +---+---+---+---+---+---+ 
 | P | y | t | h | o | n | 
 +---+---+---+---+---+---+ 
 0   1   2   3   4   5   6 
-6  -5  -4  -3  -2  -1 
C:\xxx>set var=Python

C:\xxx>set var
var=Python

C:\xxx>echo %var:~-5%
ython

C:\xxx>echo %var:~0,-1%
Pytho

C:\xxx>echo %var:~,-1%  ←第一引数省略
Pytho

C:\xxx>set var
var=Python

パラメータに日本語(DBCS)を含む場合、文字数は日本語での文字数。 例えば「にほんご」なら4文字である。

なお、本機能は環境変数の参照時に働く。 バッチパラメータには使えないので、その場合は一旦、適当な環境変数へ代入する。

offset, len をバッチパラメータで与える事は可能(環境変数の遅延展開が必要)。 次は %1=対象文字列、%2=offset、%3=len としたバッチファイルの例。

@echo off
setlocal EnableDelayedExpansion
set var=%1
echo !var:~%2,%3!
endlocal

文字列操作(置換)

set のヘルプに「環境変数の置換」とあるので set でしか使えないと思っていたが、参照時に置換するようだ。
環境変数が置き換わる訳でなく、置き換わった文字列を返すもの。
なお、大/小文字はASCIIの英字のみならず、全角の英字も問答無用で同一視されるので要注意!

%hoge:s1=s2%

hoge=123 の状態から 12456 が欲しければ

echo %hoge:3=456%

とする。変数hogeは変わらない。エコーされるだけ。
環境変数を読み取る時に置換して返す、と言うもの。
環境変数hoge そのものを置換するには

set hoge=%hoge:3=456%

ワイルドカード

ワイルドカードとは言えないが、アスタリスク(*)について説明が有る。

"文字列1"をアスタリスクで始め、展開された出力の先頭から、文字列1 の残りの部分が最初に現れるまでのすべてを一致させることもできます。

何言ってるかワカらぬので試してみる…

set var=1234_abc_abc_abc
echo %var:abc=ABC%	--> 1234_ABC_ABC_ABC ...(1)
echo %var:*abc=ABC%	--> ABC_abc_abc ........(2)
echo %var:ab*=AB%	--> 1234_abc_abc_abc ...(3)

(1)は普通の置換
(2)の例で分かるのは「最初にマッチした部分しか置換しない」
(3)の例で分かるのは「アスタリスクは先頭に書かないと働かない」

言わんとする処は大体分かった。要するに (1)でなく、(2)を実現させたかったのであろう。案外、大事な機能かも知れない。 しかし、コマンドラインのワイルドカードの処理や、正規表現に倣えば、(3)の結果は "AB" を期待したい処。

文字列操作(比較、検索)

単語同士や文字同士の比較
if~== や EQU で可。/I で大・小文字の同一視も可能。

部分一致を知りたい場合
strcmp サブルーチンを書いてみた。

部分一致した位置を知りたい場合
strstr サブルーチンを書いてみた。

文字列操作(分割)

offset, len による処理が素直で万能だけど、for /F で delims= に区切りを指定する方法も有る。

例えばファイルのフルパス文字列をドライブ、パス、ファイル名に分割するには %~dpnx 辺りで一発だが、階層ディレクトリをも分割したいとすると…

分割数は想定せぬものとしたいので分割要素が無くなるまで for /F を繰り返す。

  set var=%~1
:L1
  if "%var%" EQU "" exit /b
  for /F "tokens=1* delims=\" %%a in ("%var%") do (
    echo %%a
    set var=%%b
  )
  goto :L1

これに例えば "C:\Windows\Hoge\Foo\Bar\file.txt" を食わせれば、結果は次の通り。

C:
Windows
Hoge
Foo
Bar
file.txt

但し、delims= に指定する区切りは、連続している場合には1個の区切りと見做されるが如く振る舞うので、CSV のような列の位置が意味を持つデータには禁物である。空の列を認識出来ない。

また、for /F は、文字でなく特定単語のような文字列を区切りには出来ない。

更新履歴:

2020-7-10
右寄せ(揃え)表示を追加。
2020-6-28
負の値を使った例を追加。

Home / Windows:バッチファイル - 文字列処理

© 2008 usskim    http://usskim.web.fc2.com/
inserted by FC2 system