【bat】バッチファイルで文字列を切り出す方法完全ガイド|:~構文・FOR /F・長さ取得・トリム・よくあるエラーまで

【bat】バッチファイルで文字列を切り出して抽出する方法 bat

バッチファイルで「ファイル名から拡張子を除いた部分だけ取り出したい」「日付文字列から年・月・日を分けたい」「CSVの特定フィールドを抽出したい」と思ったことはありませんか?

バッチファイルには %変数名:~開始位置,文字数% という構文があり、文字列の任意の部分を切り出せます。本記事ではこの基本構文から、FOR /F による区切り文字での分割、文字列の長さ取得、空白のトリム、そして遅延展開が必要な場面まで、実務でよく使うパターンをすべて解説します。

この記事でわかること

  • %変数名:~開始,長さ% 構文の使い方(先頭・末尾・マイナスインデックス)
  • FOR /F を使った区切り文字での分割(CSV・メールアドレス・パス)
  • 文字列の長さをバッチファイルで取得する方法
  • 先頭・末尾の空白を除去するトリム処理
  • 遅延展開(enabledelayedexpansion)が必要な場面と注意点
  • よくあるエラーと対処法
スポンサーリンク

基本構文:位置と文字数で切り出す

バッチファイルの文字列切り出しは set コマンドのサブストリング機能を使います。

%変数名:~開始位置,文字数%
パラメータ 説明 省略時の動作
開始位置 0から始まるインデックス(先頭=0)
文字数 切り出す文字数 省略すると末尾まで取得

先頭から切り出す

@echo off
set str=Hello, World!

:: 先頭から5文字切り出す
set result=%str:~0,5%
echo %result%
:: 出力: Hello

位置を指定して切り出す

@echo off
set str=Hello, World!

:: 7文字目から5文字切り出す(インデックスは0始まり)
set result=%str:~7,5%
echo %result%
:: 出力: World

指定位置から末尾まで取得

文字数を省略すると、開始位置から文字列の末尾まで取得できます。

@echo off
set str=Hello, World!

:: 7文字目から末尾まで
set result=%str:~7%
echo %result%
:: 出力: World!

末尾から切り出す(マイナスインデックス)

開始位置にマイナスの値を指定すると、文字列の末尾からの位置を指定できます。

@echo off
set str=Hello, World!

:: 末尾から6文字取得
set result=%str:~-6%
echo %result%
:: 出力: orld!

:: 末尾から6文字目の位置から3文字取得
set result=%str:~-6,3%
echo %result%
:: 出力: orl
マイナスインデックスの注意点
%str:~-6% は末尾6文字を返します(Pythonの str[-6:] と同じ感覚)。
ただし %str:~-6,-2% のような「末尾から末尾まで」の指定はバッチではできません。

よく使う切り出しパターン

日付から年・月・日を取り出す

%DATE% 変数から年・月・日を個別に取り出せます(OS設定によってフォーマットが異なる点に注意)。

@echo off
:: %DATE% の形式: 2026/03/18 (火) など(環境依存)
set today=%DATE%

:: yyyy/mm/dd 形式の場合
set year=%today:~0,4%
set month=%today:~5,2%
set day=%today:~8,2%

echo 年: %year%  月: %month%  日: %day%
:: 出力: 年: 2026  月: 03  日: 18

:: yyyymmdd 形式のファイル名に使う
set datestamp=%year%%month%%day%
echo output_%datestamp%.log
:: 出力: output_20260318.log
%DATE%のフォーマットは環境依存
Windows の地域設定によって形式が変わります(yyyy/mm/ddmm/dd/yyyy など)。スクリプトを他の環境でも使う場合は wmic os get LocalDateTime で固定フォーマットを取得することを推奨します。

時刻から時・分・秒を取り出す

@echo off
:: %TIME% の形式: 14:30:05.12
set now=%TIME%

set hour=%now:~0,2%
set minute=%now:~3,2%
set second=%now:~6,2%

echo %hour%時%minute%分%second%秒
:: 出力: 14時30分05秒

ファイルパスからファイル名・拡張子を取り出す

FOR 文の変数修飾子を使う方法が最も確実です。

@echo off
set filepath=C:\Users\admin\Documents\report.xlsx

:: FOR文でファイル名・拡張子を取得
for %%f in ("%filepath%") do set filename=%%~nxf
echo ファイル名: %filename%
:: 出力: report.xlsx

:: 拡張子なしのファイル名
for %%f in ("%filepath%") do set name=%%~nf
echo 名前: %name%
:: 出力: report

:: 拡張子のみ
for %%f in ("%filepath%") do set ext=%%~xf
echo 拡張子: %ext%
:: 出力: .xlsx
%%~nxf などの修飾子まとめ
%%~nf: 拡張子なしのファイル名 / %%~xf: 拡張子 / %%~nxf: ファイル名+拡張子 / %%~dpf: ドライブ+パス / %%~ff: フルパス

FOR /F で区切り文字による分割

FOR /Fdelims(区切り文字)と tokens(取得位置)を使うと、特定の文字で分割した各フィールドを取得できます。

カンマ区切りで分割(CSV形式)

@echo off
set line=田中太郎,25,東京都

for /f "tokens=1,2,3 delims=," %%a in ("%line%") do (
  echo 名前: %%a
  echo 年齢: %%b
  echo 住所: %%c
)
:: 出力:
:: 名前: 田中太郎
:: 年齢: 25
:: 住所: 東京都

メールアドレスを@で分割

@echo off
set addr=user@example.com

:: @より前(ユーザー名)
for /f "tokens=1 delims=@" %%a in ("%addr%") do set user=%%a
echo ユーザー名: %user%
:: 出力: user

:: @より後(ドメイン)
for /f "tokens=2 delims=@" %%a in ("%addr%") do set domain=%%a
echo ドメイン: %domain%
:: 出力: example.com

複数の区切り文字を同時に指定

@echo off
set str=2026-03-18_report

:: - と _ 両方を区切り文字にする
for /f "tokens=1,2,3,4 delims=-_" %%a in ("%str%") do (
  echo 年: %%a
  echo 月: %%b
  echo 日: %%c
  echo 名称: %%d
)
FOR /F の tokens 上限に注意
tokensで指定できる変数は最大26個(%%a〜%%z)です。また delims= を省略するとスペース・タブが区切り文字になります。先頭のスペースを含む値を取得したい場合は "tokens=* delims=" を使います。

文字列の長さを取得する

バッチファイルには文字列長を返す組み込み関数がありません。FOR /L ループでカウントする方法が定番です。

@echo off
setlocal enabledelayedexpansion

set str=Hello, World!
set len=0

:loop
if "!str:~%len%,1!" NEQ "" (
  set /a len+=1
  goto loop
)

echo 文字列の長さ: %len%
:: 出力: 文字列の長さ: 13
PowerShell を使う方が簡単
文字列長の取得は PowerShell を呼ぶ方がシンプルです:
for /f %%a in ('powershell -command "\"Hello\".Length"') do set len=%%a

空白のトリム(先頭・末尾のスペース除去)

バッチには trim 関数がないため、FOR /F を使って空白をトリムします。

先頭・末尾の空白を除去

@echo off
set str=  Hello, World!  

:: FOR /Fで先頭の空白を除去(tokens=* delims= はスペース区切りを無視)
for /f "tokens=* delims= " %%a in ("%str%") do set trimmed=%%a
echo [%trimmed%]
:: 出力: [Hello, World!  ] ← 先頭のみ除去

:: 末尾の空白は除去が複雑なため、PowerShell推奨
for /f "delims=" %%a in ('powershell -command "''  Hello  ''.Trim()"') do set trimmed=%%a
echo [%trimmed%]
:: 出力: [Hello]

文字列の置換で切り出す

不要な部分を空文字で置換することで、実質的な切り出しができます。

@echo off
set str=ABC-DEF-GHI

:: "ABC-" を削除して "DEF-GHI" を取得
set result=%str:ABC-=%
echo %result%
:: 出力: DEF-GHI

:: 拡張子を除去(置換で擬似的なパス処理)
set filename=report.xlsx
set noext=%filename:.xlsx=%
echo %noext%
:: 出力: report

遅延展開が必要な場面

ループ内で切り出した文字列を使う場合は、遅延展開(enabledelayedexpansion)が必要です。

ループ内での動的な切り出し(遅延展開あり)

@echo off
setlocal enabledelayedexpansion

set str=ABCDEFGHIJ

:: 1文字ずつ切り出して表示
for /l %%i in (0,1,9) do (
  set char=!str:~%%i,1!
  echo %%i文字目: !char!
)
:: 出力:
:: 0文字目: A
:: 1文字目: B
:: ... 以下略

遅延展開なし(NG例)

@echo off
:: NG: 遅延展開なし
set str=ABCDEFGHIJ
for /l %%i in (0,1,9) do (
  set char=%str:~%%i,1%
  echo %char%
)
:: 出力: (空白が10回) ← %%iがループ前に展開されてしまう
遅延展開のポイント

  • ループの内側で変数の値を参照するには !変数名! を使う
  • %変数名% はスクリプトのパース時(実行前)に展開されてしまう
  • setlocal enabledelayedexpansion は必ずスクリプトの先頭で宣言する

実用パターン集

ログファイル名に日時スタンプを付ける

@echo off
setlocal

:: wmic で確実な日時フォーマット取得
for /f "skip=1 tokens=1" %%a in ('wmic os get localdatetime') do set dt=%%a
:: dt = 20260318143005.000000+540 の形式

set datestamp=%dt:~0,8%
set timestamp=%dt:~8,6%

set logfile=app_%datestamp%_%timestamp%.log
echo %logfile%
:: 出力: app_20260318_143005.log

URLからパスだけを取り出す

@echo off
set url=https://example.com/path/to/page

:: https:// を除去
set path=%url:https://=%
:: path = example.com/path/to/page

:: 最初の / 以降を取得(FOR /F 活用)
for /f "tokens=2 delims=/" %%a in ("%path%") do set part=%%a
echo %part%
:: 出力: path

テキストから特定フォーマットを抽出

@echo off
setlocal enabledelayedexpansion

:: "VERSION=1.2.3" 形式からバージョン番号だけ取得
set line=VERSION=1.2.3

:: = 以降を取得
for /f "tokens=2 delims==" %%a in ("%line%") do set version=%%a
echo バージョン: %version%
:: 出力: バージョン: 1.2.3

:: メジャーバージョンのみ
set major=%version:~0,1%
echo メジャーバージョン: %major%
:: 出力: メジャーバージョン: 1

切り出し構文まとめ

やりたいこと 構文
先頭からN文字 %var:~0,N% %str:~0,5% → 先頭5文字
M文字目からN文字 %var:~M,N% %str:~7,5% → 7文字目から5文字
M文字目から末尾まで %var:~M% %str:~7% → 7文字目以降すべて
末尾からN文字 %var:~-N% %str:~-5% → 末尾5文字
区切り文字で分割 for /f "tokens=N delims=X" カンマ・スペース・@など
特定文字列を除去 %var:文字列=% %str:ABC-=% → ABC-を削除
ループ内の動的切り出し !var:~%%i,1! 遅延展開必須

よくあるエラーと対処法

切り出しても空文字が返ってくる

インデックスが文字列の範囲外の場合、空文字が返ります。

@echo off
set str=Hello

:: 長さ5の文字列で10文字目を指定
set result=%str:~10,1%
echo [%result%]
:: 出力: [] ← 空文字(エラーにはならない)

ループ内で値が変わらない(遅延展開忘れ)

@echo off
:: NG: 遅延展開なし → %%i の展開タイミングが間違い
set str=ABCDEF
for /l %%i in (0,1,5) do (
  echo %str:~%%i,1%  ← これは空または文字化けする
)

:: OK: 遅延展開あり
setlocal enabledelayedexpansion
set str=ABCDEF
for /l %%i in (0,1,5) do (
  echo !str:~%%i,1!
)
最も多いミス:遅延展開の忘れ
ループ内で %変数%:~%%i,1% を使っても動きません。setlocal enabledelayedexpansion を宣言して !変数!:~%%i,1! を使ってください。

スペースを含む文字列が途切れる

@echo off
set str=Hello World

:: NG: FOR /F はデフォルトでスペースが区切り文字になる
for /f %%a in ("%str%") do echo %%a
:: 出力: Hello ← World が切り捨てられる

:: OK: delims= を空にしてスペースを区切り文字から除外
for /f "delims=" %%a in ("%str%") do echo %%a
:: 出力: Hello World

特殊文字(!、^、&)を含む文字列

@echo off
setlocal enabledelayedexpansion

:: ! は遅延展開で特殊文字になるため ^ でエスケープ
set str=Hello^!World
echo %str%
:: 出力: Hello!World

:: 切り出しの際も問題なし
set result=!str:~0,5!
echo %result%
:: 出力: Hello

よくある質問

Q. %変数:~0,5% と %変数:~0,-5% の違いは何ですか?
A. %var:~0,5% は先頭から5文字を取得します。一方 %var:~0,-5% は先頭から末尾5文字を除いた部分を返します。例えば “ABCDEFGHIJ”(10文字)なら :~0,-5% は “ABCDE”(末尾5文字の “FGHIJ” を除いた部分)を返します。
Q. 日本語(全角)文字列の切り出しはできますか?
A. バッチファイルの :~ 構文はバイト単位ではなく文字数単位で動作しますが、コードページの影響を受けます。日本語を含む場合は chcp 65001(UTF-8)に設定して動作確認してください。PowerShell を使う方が安全です。
Q. FOR /F で取得した値が空になることがあります。なぜですか?
A. 主な原因は3つです。①変数に値がセットされていない(タイポ等)、②区切り文字の設定ミス(delims=, なのに区切り文字が違う)、③スペースを含む値で delims= の指定漏れ。echo [%変数%] でブラケット付きでデバッグ表示すると原因が特定しやすいです。
Q. Python の str[2:5] のようなスライス記法はバッチでも使えますか?
A. 直接の対応はありませんが、%var:~2,3%(2文字目から3文字)が近い動作をします。末尾を除外する str[:-2]%var:~0,-2% で対応できます。ただしバッチのインデックスは0始まりで Python と同じです。
Q. 大文字・小文字の変換はできますか?
A. %var:lower=upper% のような直接変換はできません。PowerShell を呼び出す方法が現実的です:for /f %%a in ('powershell -command "''hello''.ToUpper()"') do set upper=%%a。これで “HELLO” が取得できます。

まとめ

バッチファイルの文字列切り出しポイント

  • %var:~開始,長さ% が基本構文(インデックスは0始まり)
  • マイナスインデックスで末尾からの位置指定が可能
  • 区切り文字での分割は FOR /F "tokens=N delims=X"
  • ループ内での動的切り出しには 遅延展開!var:~%%i,1!)が必須
  • 文字列長の取得・空白トリムなど高度な処理は PowerShell 活用が現実的

あわせて読みたい