はじめに
awkはテキスト処理に特化した強力なツールであり、ログ解析やデータ整形の現場で広く使われています。
その中でもsubstrは文字列の一部を切り出すための基本かつ重要な関数です。
しかし、初学者にとっては引数の意味や他の関数との組み合わせ方でつまずきやすいポイントでもあります。
本記事ではawkのsubstrの基本から応用までを、実務で役立つ視点で丁寧に解説します。
参考: GNU awk
awkのsubstr関数の基本構文と引数の定義
ファイル作成
cat << 'EOF' > input.txt
Hello,awk,substr,function
EOF
実行コマンド
awk '{ print substr($0,1,5) }' input.txt
実行結果
Hello
実行コマンド
awk '{ print substr($0,7,3) }' input.txt
実行結果
awk
実行コマンド
awk '{ print substr($0,11) }' input.txt
実行結果
substr,function
仕組み
| 要素 | 内容 |
|---|---|
| substr(文字列, 開始位置, 長さ) | 基本構文 |
| 文字列 | 対象となる文字列(例:$0は1行全体) |
| 開始位置 | 1から始まるインデックス |
| 長さ | 省略可能(省略時は末尾まで取得) |
| 戻り値 | 指定した範囲の部分文字列 |
解説
substrは指定した位置から文字列を切り出す関数です。
開始位置は1始まりで、長さを省略すると末尾まで取得されます。
第3引数(長さ)を省略した際の挙動と活用シーン
ファイル作成
cat << 'EOF' > input.txt
HelloWorld
AWKsubstrExample
EOF
実行コマンド
awk '{print substr($0,6)}' input.txt
実行結果
World
bstrExample
実行コマンド
awk '{print substr($0,1)}' input.txt
実行結果
HelloWorld
AWKsubstrExample
仕組み
| 項目 | 内容 |
|---|---|
| 関数 | substr(文字列, 開始位置, 長さ) |
| 第3引数省略時 | 開始位置から末尾まで全て取得 |
| 開始位置の基準 | 1から開始(0ではない) |
| 戻り値 | 指定位置以降の部分文字列 |
| 活用シーン | 「途中から最後まで取得したい」ログ解析や文字列加工 |
解説
第3引数を省略すると「開始位置から末尾まで」を一括取得できるため、可変長データの後半部分を取り出すのに便利です。
特にログや区切りが曖昧な文字列処理でシンプルに書けるのが強みです。
index関数との組み合わせによる動的な切り出し開始位置の特定
ファイル作成
cat << 'EOF' > input.txt
apple:100
banana:200
cherry:300
EOF
実行コマンド
awk -F: '{ pos = index($0, ":"); print substr($0, pos+1) }' input.txt
実行結果
100
200
300
実行コマンド
awk -F: '{ pos = index($0, ":"); print substr($0, 1, pos-1) }' input.txt
実行結果
apple
banana
cherry
仕組み
| 要素 | 内容 |
|---|---|
| index($0, ":") | 行内で「:」の位置を取得 |
| pos | 切り出し開始位置の基準 |
| substr($0, pos+1) | 「:」以降を抽出(値部分) |
| substr($0, 1, pos-1) | 「:」より前を抽出(キー部分) |
| $0 | 行全体を対象に処理 |
解説
indexで位置を動的に取得することで、区切り位置が変わっても柔軟に対応できます。
substrと組み合わせることで、任意の位置からの文字列抽出が簡単に実現できます。
length関数を併用した末尾からの文字列抽出
ファイル作成
cat << 'EOF' > input.txt
apple
banana
cherry
EOF
実行コマンド
awk '{ print substr($0, length($0)-2, 3) }' input.txt
実行結果
ple
ana
rry
仕組み
| 要素 | 内容 |
|---|---|
| length($0) | 行全体の文字数を取得 |
| substr($0, 開始位置, 文字数) | 指定位置から文字列を抽出 |
| length($0)-2 | 末尾3文字の開始位置を計算 |
| $0 | 行全体を表す |
解説
lengthで文字数を取得し、末尾からの開始位置を計算することで後ろからの抽出が可能になります。
substrと組み合わせるのがポイントです。
if文とsubstrを組み合わせた特定パターン行のフィルタリング
ファイル作成
cat << 'EOF' > input.txt
apple_001
banana_002
apple_123
orange_999
apple_abc
EOF
実行コマンド
awk '{ if (substr($0,1,5) == "apple" && substr($0,7,3) ~ /^[0-9]{3}$/) print }' input.txt
実行結果
apple_001
apple_123
仕組み
| 要素 | 内容 |
|---|---|
| substr($0,1,5) | 先頭から5文字を取得("apple" 判定) |
| substr($0,7,3) | 7文字目から3文字取得(数値部分) |
| ~ /^[0-9]{3}$/ | 3桁の数字かどうか正規表現で判定 |
| if 条件 | 「appleで始まり、かつ3桁数字」でフィルタ |
| 条件に一致した行のみ出力 |
解説
substrで文字位置を切り出し、ifで条件分岐することで、特定パターンの行だけを効率よく抽出できます。
awk単体で柔軟なフィルタリングが可能です。
forループを用いた文字列の1文字分割と配列格納
ファイル作成
cat << 'EOF' > input.txt
hello
EOF
実行コマンド
awk '{
for(i=1;i<=length($0);i++){
arr[i]=substr($0,i,1)
}
for(i=1;i<=length($0);i++){
print arr[i]
}
}' input.txt
実行結果
h
e
l
l
o
仕組み
| 処理 | 内容 |
|---|---|
| length($0) | 行の文字数を取得 |
| substr($0,i,1) | i番目の1文字を取得 |
| arr[i] | 1文字ずつ配列に格納 |
| for(i=1;i<=length($0);i++) | 先頭から順番に処理 |
| print arr[i] | 配列の中身を順番に出力 |
解説
awkのsubstrを使うことで文字列を1文字ずつ分解できます。
なおfor(i in arr)を使うと配列の順序が保証されず、2 3 4 5 1のように並びが崩れる場合があるため、インデックス指定のfor文を使うのが安全です。
固定長テキストデータのパースにおけるsubstrの効率的な運用
ファイル作成
cat << 'EOF' > input.txt
00001Yamada Tokyo 030
00002Suzuki Osaka 045
00003Tanaka Nagoya 028
EOF
実行コマンド
awk '{id=substr($0,1,5); name=substr($0,6,9); city=substr($0,15,10); age=substr($0,25,3); printf "ID:%s Name:%s City:%s Age:%s\n", id, name, city, age}' input.txt
実行結果
ID:00001 Name:Yamada City:Tokyo Age:030
ID:00002 Name:Suzuki City:Osaka Age:045
ID:00003 Name:Tanaka City:Nagoya Age:028
実行コマンド
awk '{id=substr($0,1,5); name=substr($0,6,9); city=substr($0,15,10); age=substr($0,25,3);
gsub(/^ +| +$/,"",name); gsub(/^ +| +$/,"",city);
printf "%s,%s,%s,%s\n", id, name, city, age}' input.txt
実行結果
00001,Yamada,Tokyo,030
00002,Suzuki,Osaka,045
00003,Tanaka,Nagoya,028
仕組み
| 項目 | 内容 |
|---|---|
| substr($0,1,5) | 1文字目から5文字取得(ID) |
| substr($0,6,9) | 6文字目から9文字取得(名前) |
| substr($0,15,10) | 15文字目から10文字取得(都市) |
| substr($0,25,3) | 25文字目から3文字取得(年齢) |
| $0 | 行全体の文字列 |
| gsub | 空白のトリミング |
解説
固定長データは区切り文字がないため、位置指定で切り出すawk substrが非常に高速でシンプルです。
事前に桁位置を固定すれば、安定してパースできるのが利点です。
正規表現による置換関数(sub|gsub)とsubstrの使い分け基準
ファイル作成
cat << 'EOF' > input.txt
apple 123 orange
banana 456 grape
cherry 789 melon
EOF
実行コマンド
awk '{print substr($1,1,3)}' input.txt
実行結果
app
ban
che
実行コマンド
awk '{sub(/[0-9]+/,"NUM"); print}' input.txt
実行結果
apple NUM orange
banana NUM grape
cherry NUM melon
実行コマンド
awk '{gsub(/[aeiou]/,"_"); print}' input.txt
実行結果
_ppl_ 123 _r_ng_
b_n_n_ 456 gr_p_
ch_rry 789 m_l_n
仕組み
| 機能 | 関数 | 対象範囲 | 特徴 | awk substrとの違い |
|---|---|---|---|---|
| 部分取得 | substr | 位置指定 | 指定位置から文字列切り出し | 置換はしない |
| 単一置換 | sub | 最初の1箇所 | 最初に一致した部分のみ置換 | パターンベース |
| 全体置換 | gsub | すべての一致箇所 | マッチした箇所をすべて置換 | 繰り返し適用 |
解説
substrは「位置」で切り出し、sub/gsubは「正規表現パターン」で置換するのが判断基準。
用途が“構造”か“パターン”かで使い分ける。
特定記号の間にある文字列の抽出方法
ファイル作成
cat << 'EOF' > input.txt
abc[hello]def
123[world]456
xxx[test123]yyy
EOF
実行コマンド
awk '{
start = index($0, "[") + 1
end = index($0, "]")
print substr($0, start, end - start)
}' input.txt
実行結果
hello
world
test123
仕組み
| 要素 | 内容 |
|---|---|
| index($0, "[") | [ の位置を取得 |
| index($0, "]") | ] の位置を取得 |
| start | 抽出開始位置([の次) |
| end - start | 抽出する文字数 |
| substr($0, start, length) | 指定範囲の文字列を抽出 |
解説
indexで開始と終了位置を取得し、substrでその範囲を切り出しています。
区切り文字に依存せず柔軟に抽出できる方法です。
awkとsubstrを使いこなすための実践的なまとめ
awkのsubstrはシンプルながら応用範囲の広い関数です。
基本構文を理解した上で、第3引数の省略やindex、lengthとの組み合わせを覚えることで、実務レベルの処理が可能になります。
また、if文やforループと組み合わせることで、より柔軟なデータ加工が実現できます。
固定長データの処理やパターン抽出では特に威力を発揮し、subやgsubとの使い分けを意識することでコードの可読性と効率も向上します。
awkとsubstrを正しく理解し、小さな処理から積み重ねていくことがスキル向上への近道です。

![[sed] 実行して理解 指定した範囲の行を削除 文字列のsed](https://running-terminal-commands.com/wp-content/uploads/thumbnail_sed_1920_1080.png.webp)