導入: なぜ今、SEARCH関数なのか
メインフレームでのデータ処理において、可変長のテキストデータやログファイルから特定の情報を抽出する作業は日常茶飯事です。多くのエンジニアがINDEX関数で一文字ずつ判定したり、ループを回して力技で解決しようとしますが、実はSEARCH関数を使うことで、そのコードは劇的に短く、かつ高速になります。本稿では、文字列の中から複数の区切り文字を一度に探す「トークナイズ」の効率的な手法を解説します。
基礎知識: SEARCH / SEARCHR とは
SEARCH関数は、指定した文字列の中から「検索対象として指定した文字集合」のいずれかが出現する最初の位置を返す関数です。また、SEARCHR関数はその逆で、文字列の末尾(右側)から検索を開始します。
例えば、カンマやスペース、タブなど、複数の区切り文字が混在するデータ構造を扱う際、INDEX関数では個別に検索する必要がありますが、SEARCH関数なら引数に区切り文字を並べるだけで、どれか一つでも見つかった瞬間にその位置を教えてくれます。これは、現代のプログラミングにおける正規表現の「文字クラス([abc])」と同じ役割を果たします。
実装/解決策: トークナイズの効率化
この関数の真価は、パーサ(解析器)の実装にあります。文字列を特定の区切り文字で分割する際、SEARCH関数で区切り文字の出現位置を特定し、SUBSTR関数で切り出すという処理を繰り返すことで、可変長の入力データから効率よく値を取り出すことができます。
サンプルプログラム: 複数区切り文字による文字列の切り出し
以下は、カンマ、セミコロン、タブのいずれかで区切られた文字列から、要素を一つずつ切り出す処理のサンプルです。
/ 検索対象の文字列 /
DCL LINE CHAR(100) INIT('ID001,NAME;DATA END');
DCL POS FIXED BIN(15);
DCL START_POS FIXED BIN(15) INIT(1);
DCL ITEM CHAR(20);
/ SEARCH関数で区切り文字(カンマ、セミコロン、タブ)を探す /
POS = SEARCH(SUBSTR(LINE, START_POS), ' ,;\t');
DO WHILE(POS > 0);
/ 見つかった位置までを切り出し /
ITEM = SUBSTR(LINE, START_POS, POS - 1);
PUT SKIP LIST('抽出された項目: ' || ITEM);
/ 次の検索開始位置を更新 /
START_POS = START_POS + POS;
POS = SEARCH(SUBSTR(LINE, START_POS), ' ,;\t');
END;
応用・注意点: 現場で陥りやすい罠
SEARCH関数を使用する際に注意すべき点が二つあります。
一つ目は「戻り値の判定」です。見つからなかった場合、0が返されます。ループ処理の終了条件として「POS > 0」を必ず設定してください。
二つ目は「検索対象文字列の指定」です。SEARCH関数はあくまで「指定した文字集合のいずれか」を探します。もし検索したい文字の中に一重引用符(’)が含まれている場合は、エスケープ処理が必要になるため注意が必要です。
また、文字列の末尾から処理を逆算したい場合は、SEARCHRを使用することで、パスの解析やファイル名の抽出などが驚くほど簡潔になります。古いコードを保守する際、ループ内にINDEX関数のネストを見つけたら、SEARCH関数への置き換えを検討してみてください。可読性が向上するだけでなく、処理負荷の軽減も期待できます。

コメント