【入門編】TRIM, LEFT, RIGHT関数の空白除去ロジックとパフォーマンス – PL/Iの基本構文とデータ制御実践ガイド

メインフレームの文字列操作、怖くない!PL/IのTRIM、LEFT、RIGHT関数を徹底解説

「JavaやCOBOLは触ったことあるけど、PL/Iってなんか難しそう…」
「メインフレームのバッチ処理、どうやって文字列を扱ってるんだろう?」

そんな風に思っているあなた、ようこそ!
このブログでは、PL/Iの文字列操作関数の中でも特に頻繁に登場する `TRIM`、`LEFT`、`RIGHT` について、その基本からちょっとした落とし穴まで、メインフレームの現場で長年培ってきた経験を元に、分かりやすく、そして何より「怖くない」ように解説していきます。

識別子(変数名)の命名規則、実はシンプルなんです!

PL/Iを初めて触る方がまず戸惑うのが、識別子、つまり変数名やプログラム名の付け方かもしれませんね。でも、心配いりません。基本はとってもシンプルなんです。

  • 英字で始まること: まずはAからZのどれかで始めましょう。
  • 英数字と「@」「#」「$」が使える: 最初の文字以降は、数字や、@、#、$といった記号も使えます。
  • 全角文字は使えない: 日本語などの全角文字は使えません。
  • 予約語は使わない: これは他の言語でも同じですよね。PL/Iにも「IF」とか「DO」といった、特別な意味を持つ「予約語」がありますが、これらを識別子として使うことはできません。

例えば、こんな変数はOKです。

1
MY_VARIABLE
ACCOUNT_NUM$
CUSTOMER@ID
ITEM123

逆に、こんなのはNGです。

1
1ST_ITEM / 数字で始まっている /
MY-VARIABLE / ハイフンは使えない /
IF / 予約語 /

「え、ハイフンもダメなの?」と思ったあなた、鋭い!PL/Iでは、単語を区切るのにハイフンではなく、アンダースコア `_` を使うのが一般的です。この辺りは、COBOLの `MOVE SPACES TO DATA.` といった雰囲気とは少し違いますよね。

データストレージ属性、PL/Iだとこう書く!

PL/Iのデータ宣言は、少し独特に感じるかもしれません。例えば、文字列を扱う `CHARACTER` 型の宣言を見てみましょう。

1
DECLARE MY_STRING CHARACTER(10);

これは、「`MY_STRING` という名前で、10文字分の長さを持つ文字列型の変数を用意してくださいね」という意味です。

ここでポイントなのが、`CHARACTER` の後に続く `(10)` の部分。これは、その文字列が「固定長」であることを示しています。つまり、たとえ1文字しか入れてなくても、10文字分のメモリ領域が確保されるんです。JavaのString型のように、中身の長さに合わせてメモリが自動で調整されるわけではない、という点がレガシーシステムらしい、と言えるかもしれませんね。

TRIM、LEFT、RIGHT関数:文字列操作の三銃士!

さて、いよいよ本題です。文字列を扱う上で、余分な空白を削除したり、指定した長さに揃えたりする処理は、バッチ処理では避けて通れません。そこで活躍するのが `TRIM`、`LEFT`、`RIGHT` 関数です。

TRIM関数:両側の不要な空白をスッキリ!

`TRIM` 関数は、文字列の両端にある空白文字を取り除いてくれる関数です。

例えば、こんなデータがあったとしましょう。

1
DECLARE CUSTOMER_NAME CHARACTER(30) VARYING; / VARYINGは可変長 /
DECLARE TRIMMED_NAME CHARACTER(30) VARYING;

CUSTOMER_NAME = ‘ 山田 太郎 ‘; / 前後に空白がある /

TRIMMED_NAME = TRIM(CUSTOMER_NAME);

この場合、`TRIMMED_NAME` には `’山田 太郎’` という、前後の空白が取り除かれた文字列が入ります。まるで、ごちゃごちゃした部屋を片付けてスッキリさせたような気分になりますよね!

LEFT関数:左側を基準に文字列を切り出す!

`LEFT` 関数は、文字列の左側から指定した文字数だけを取り出す関数です。

1
DECLARE ITEM_CODE CHARACTER(10) VARYING;
DECLARE FIRST_THREE_CHARS CHARACTER(3);

ITEM_CODE = ‘ABC1234567’;

FIRST_THREE_CHARS = LEFT(ITEM_CODE, 3);

このコードでは、`FIRST_THREE_CHARS` には `’ABC’` という文字列が入ります。元の文字列が指定した文字数より短かった場合は、そのままの長さで取得されます。

RIGHT関数:右側を基準に文字列を切り出す!

`RIGHT` 関数は、`LEFT` 関数とは逆に、文字列の右側から指定した文字数だけを取り出します。

1
DECLARE LONG_STRING CHARACTER(50) VARYING;
DECLARE LAST_FIVE_CHARS CHARACTER(5);

LONG_STRING = ‘これは非常に長い文字列です。’;

LAST_FIVE_CHARS = RIGHT(LONG_STRING, 5);

この場合、`LAST_FIVE_CHARS` には `’です。’` という文字列が入ります。

EBCDIC環境とスペース以外の文字での注意点

さて、ここからがPL/I、特にメインフレーム環境で触れる際に、ちょっとだけ注意が必要なポイントです。

PL/Iで「空白」というと、一般的にはASCII環境では `X’20’`、EBCDIC環境では `X’40’` の文字を指します。`TRIM` 関数も、デフォルトではこれらの文字を対象として空白とみなして除去します。

しかし、もし、文字列の端に `X’40’` 以外の、例えばタブ文字や制御文字といった、いわゆる「見えない文字」がくっついている場合、`TRIM` 関数はその文字を「空白」とはみなさず、除去してくれないことがあるんです。

例えば、以下のようなケースを考えてみましょう。

1
DECLARE DATA_FROM_FILE CHARACTER(50);
DECLARE CLEANED_DATA CHARACTER(50);

/ ファイルから読み込んだデータが、末尾にX’09’ (タブ文字) を含んでいるとする /
DATA_FROM_FILE = ‘データ項目’ || X’09’; / 末尾にタブ文字が付いている /

/ TRIM関数では、X’40’以外の文字は除去されない /
CLEANED_DATA = TRIM(DATA_FROM_FILE);

/ この場合、CLEANED_DATA には ‘データ項目’ || X’09’ がそのまま入ってしまう /

あれれ? `TRIM` したはずなのに、末尾のタブ文字が残ってしまった…!
こんな時、どうすればいいのでしょう?

PL/Iの `TRIM` 関数には、除去したい文字を指定するオプションがあります。

1
/ TRIM関数で、末尾のタブ文字(X’09’)を明示的に除去する /
CLEANED_DATA = TRIM(DATA_FROM_FILE, TRAILING, X’09’);

このコードでは、`TRIM` 関数の第二引数に `TRAILING` を指定することで「末尾のみ」を対象にし、第三引数に `X’09’` を指定することで「タブ文字」を明示的に除去するように指示しています。
`LEADING` を指定すれば先頭のみ、何も指定しなければ両端、という挙動になります。

これは、`LEFT` や `RIGHT` 関数にも同様の考え方が適用できます。例えば、文字列を特定の文字で埋めたい場合など、デフォルトの空白 (`X’40’`) 以外の文字でパディングしたい場合に、これらのオプションが活躍する場面があるかもしれません。

パフォーマンスについて:現場の知恵

`TRIM`、`LEFT`、`RIGHT` 関数は、文字列操作の基本であり、非常に便利です。しかし、大量のデータを処理するバッチ処理の現場では、パフォーマンスも気になるところですよね。

一般的に、これらの関数はPL/Iのコンパイラによって効率的に実装されています。しかし、もし非常に頻繁に、そして大量の文字列に対してこれらの関数を呼び出すような処理がある場合、パフォーマンスに影響が出る可能性もゼロではありません。

そんな時は、以下の点を意識すると良いかもしれません。

  • 不要な関数呼び出しを減らす: 本当に `TRIM` する必要があるのか? `LEFT` や `RIGHT` で切り出す前に、その処理は本当に必要か? を見直してみましょう。
  • 固定長文字列を有効活用する: PL/Iでは、`CHARACTER(n)` のように固定長で宣言すると、パフォーマンス上有利な場合があります。特に、長さがほぼ決まっている文字列を扱う場合は、`VARYING` よりも固定長を検討してみると良いかもしれません。
  • コンパイラの最適化レベル: PL/Iコンパイラには、最適化レベルを指定するオプションがあります。適切な最適化レベルを設定することで、生成されるコードの効率が向上することがあります。

もちろん、これらの関数が原因でパフォーマンス問題が起きるケースは稀です。まずは「正しく」文字列を操作することに集中し、もしパフォーマンスのボトルネックが見つかった場合に、これらの関数を疑ってみる、という順番で良いと思います。

まとめ

PL/Iの `TRIM`、`LEFT`、`RIGHT` 関数について、基本的な使い方から、EBCDIC環境での注意点、そしてパフォーマンスに関する現場の知恵まで、駆け足で見てきました。

最初は少し戸惑うかもしれませんが、これらの関数を使いこなせるようになれば、メインフレームの文字列処理がぐっと楽になります。
「レガシーだから難しい」なんてことはありません。一つずつ、丁寧に紐解いていけば、きっとあなたもPL/Iマスターになれるはずです!

もし、この記事を読んで「こんなケースはどうすればいいの?」「もっと詳しく知りたい!」という疑問があれば、ぜひコメントで教えてくださいね。あなたの疑問を解決するお手伝いができれば、私としても嬉しい限りです。

タイトルとURLをコピーしました