COBOLの「UNSTRING文」とは?サンプルで学ぶ文字列分割テクニック

2025年4月10日木曜日

COBOL

この記事では、COBOLプログラミングにおける強力な命令、COBOL UNSTRING文について、基本から応用まで解説していきます。

カンマ区切り(CSV)やスペース区切りといったデータを扱うとき、特定の区切り文字で文字列を分割して、それぞれの部品を別々の入れ物(項目)にキレイに格納したい場面って、結構ありますよね。

そんな時、UNSTRING文が役に立ちます。ちょっと構文がややこしそう?オプションが多くて迷う?大丈夫!この記事を読めば、そんな悩みもスッキリ解消するはずです。

この記事を読むと、こんなことができるようになりますよ。

  • UNSTRING文が何をするための命令か理解できる
  • UNSTRING文の基本的な書き方を覚えられる
  • サンプルコードを通して、具体的な使い方をマスターできる
  • 複数の区切り文字やオプションの使い分けがわかる
  • UNSTRING文を使うときの注意点を知り、ミスを防げる

COBOLの「UNSTRING文」とは?文字列分割の基本を理解しよう

まず、UNSTRING文って何者?というところから始めましょう。

簡単に言うと、「一つの長い文字列を、指定したルール(区切り文字)に従って、いくつかの短い文字列に分解して、それぞれ別の場所にしまう」ためのCOBOL命令文です。

例えば、「山田太郎,30歳,東京都」みたいなカンマで区切られたデータがあったとします。これを「名前」「年齢」「住所」という別々の入れ物(変数や項目といいます)に入れたいとき、UNSTRING文の出番です。

「カンマ(,)で区切ってね!」とUNSTRING文に指示すれば、「山田太郎」「30歳」「東京都」と分けて、指定した入れ物に順番に入れてくれる、というわけです。

昔ながらの固定長のデータだけでなく、最近よく見るCSVファイルのように、データの長さがバラバラで区切り文字で分けられているデータを扱うときに、とっても重宝しますよ。

「UNSTRING文」の基本的な書き方

では、実際にUNSTRING文をどう書くのか、その骨組み(構文)を見ていきましょう。
基本形はこんな感じです。

UNSTRING 分割したい元のデータ項目
    [ DELIMITED BY 区切り文字1 [OR 区切り文字2]... | ALL 区切り文字 ]
    INTO 格納先の項目1 [DELIMITER IN 区切り文字格納先1] [COUNT IN カウント格納先1]
         [格納先の項目2 [DELIMITER IN 区切り文字格納先2] [COUNT IN カウント格納先2]] ...
    [ WITH POINTER ポインター変数 ]
    [ TALLYING IN 格納した項目数を数える変数 ]
    [ ON OVERFLOW 命令実行後の処理 ]
    [ NOT ON OVERFLOW 命令実行後の処理 ]
END-UNSTRING.

うーん、ちょっとオプションが多いですね!でも安心してください。全部を一度に覚える必要はありません。

まずは、「どのデータを(UNSTRING)」「何で区切って(DELIMITED BY)」「どこに入れるか(INTO)」の3つが基本だと押さえておけばOKです。

UNSTRING文の全体構造

まずは、一番シンプルなUNSTRING文の構造をつかみましょう。最低限、これだけあれば動きます。

UNSTRING 分割元データ
    DELIMITED BY 区切り文字
    INTO 格納先データ1, 格納先データ2 ...
END-UNSTRING.

図でイメージするとこんな感じでしょうか。

+----------------------+     +----------------+     +---------------------+
| UNSTRING             | --> | 分割したいデータ | --> | DELIMITED BY        | --> 区切り文字(',')など
| (分割スタート!)     |     | (元の長い文字列) |     | (これで区切ってね!) |
+----------------------+     +----------------+     +---------------------+
      |
      V
+----------------------+     +----------------+     +----------------+
| INTO                 | --> | 格納先1       | --> | 格納先2       | --> ...
| (ここに入れてね!)    |     | (分割後の部品1) |     | (分割後の部品2) |
+----------------------+     +----------------+     +----------------+

この基本形を頭に入れておくと、他のオプションも理解しやすくなりますよ。

主要な句(IDENTIFIER-1, DELIMITED BY, INTO)の役割

UNSTRING文を使いこなす上で、核となる3つの「句(く)」について、もう少し詳しく見ていきましょう。

  • UNSTRINGの後 (IDENTIFIER-1に相当)
    ここには、分割したいデータが入っている項目(変数名)を書きます。例えば、WS-INPUT-DATA のような名前の項目です。
  • DELIMITED BY
    ここには、何を使って文字列を区切るかを指定します。カンマなら ',' 、スペースなら SPACE、タブ文字なら X'09' のように書きます。複数の文字を区切り文字にしたい場合は、OR でつなげたり、ALLANY を使ったりもできます(これは後で詳しく!)。
  • INTO
    ここには、分割した文字列を格納する先の項目(変数名)を順番に書きます。INTO WS-ITEM-1, WS-ITEM-2, WS-ITEM-3 のように、カンマで区切って複数指定します。分割された順番に、指定した項目へ格納されていきます。

まずはこの3つの役割をしっかり覚えましょう!

「UNSTRING文」の使い方

お待たせしました!ここからは、実際にCOBOLのコードを使いながら、UNSTRING文の使い方を具体的に見ていきましょう。

基本的な使い方:1つの区切り文字で分割

まずは一番シンプルなパターン、カンマ(,)で区切られたデータを分割してみましょう。

ソースコード

IDENTIFICATION DIVISION.
PROGRAM-ID. UNSTRING-BASIC.

DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-INPUT-DATA      PIC X(30) VALUE 'Taro Yamada,30,Tokyo'.
01 WS-NAME            PIC X(15).
01 WS-AGE             PIC X(3).  *> 文字列として受け取る
01 WS-ADDRESS         PIC X(15).

PROCEDURE DIVISION.
    DISPLAY '分割前データ: ' WS-INPUT-DATA.

    UNSTRING WS-INPUT-DATA
        DELIMITED BY ','  *> カンマで区切る
        INTO WS-NAME, WS-AGE, WS-ADDRESS *> この順番で格納
    END-UNSTRING.

    DISPLAY '--- 分割後 ---'.
    DISPLAY '名前    : ' WS-NAME.
    DISPLAY '年齢    : ' WS-AGE.
    DISPLAY '住所    : ' WS-ADDRESS.

    STOP RUN.

ソースコードの表示結果

分割前データ: Taro Yamada,30,Tokyo
--- 分割後 ---
名前    : Taro Yamada
年齢    : 30
住所    : Tokyo

どうでしょう?WS-INPUT-DATA に入っていた文字列が、カンマを境にして WS-NAME, WS-AGE, WS-ADDRESS にちゃんと分割・格納されましたね!

ポイントは、INTO句に書いた項目の順番通りにデータが入ることです。年齢(AGE)は数字ですが、まずは文字列(PIC X)として受け取るのが一般的です。後で数字に変換する必要があれば、別途処理を行います。

複数の区切り文字を使う方法 (DELIMITED BY ALL / ANY)

区切り文字が1種類だけとは限りませんよね。カンマもスペースも区切り文字として扱いたい、なんてこともあります。

そんなときは DELIMITED BY の書き方を工夫します。

例えば、カンマかスラッシュ(/)で区切りたい場合:

DELIMITED BY ',' OR '/'

または、ANY を使っても同じことができます。

DELIMITED BY ANY ',' '/'

ALL という指定もあります。これは、連続する区切り文字を1つとして扱うときに便利です。例えば、'A,,B' のようにカンマが連続しているデータを DELIMITED BY ALL ',' で分割すると、AB に分割されます(間の空っぽの部分は無視されます)。普通の DELIMITED BY ',' だと、A、空っぽ、B の3つに分割される挙動になることが多いので、違いを理解しておくと良いでしょう。

ソースコード (ANY使用例)

IDENTIFICATION DIVISION.
PROGRAM-ID. UNSTRING-MULTI-DELIM.

DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-INPUT-DATA      PIC X(30) VALUE 'Apple/Banana,Orange Mango'.
01 WS-TEMP-DATA       PIC X(30).
01 WS-FRUIT-1         PIC X(10).
01 WS-FRUIT-2         PIC X(10).
01 WS-FRUIT-3         PIC X(10).
01 WS-FRUIT-4         PIC X(10).

PROCEDURE DIVISION.
    DISPLAY '分割前データ: ' WS-INPUT-DATA.

    MOVE WS-INPUT-DATA TO WS-TEMP-DATA.

    *> スラッシュで最初に分割
    UNSTRING WS-TEMP-DATA
        DELIMITED BY '/'
        INTO WS-FRUIT-1, WS-TEMP-DATA
    END-UNSTRING.

    *> カンマで分割
    UNSTRING WS-TEMP-DATA
        DELIMITED BY ','
        INTO WS-FRUIT-2, WS-TEMP-DATA
    END-UNSTRING.

    *> スペースで分割
    UNSTRING WS-TEMP-DATA
        DELIMITED BY SPACE
        INTO WS-FRUIT-3, WS-FRUIT-4
    END-UNSTRING.

    DISPLAY '--- 分割後 ---'.
    DISPLAY '果物1   : ' WS-FRUIT-1.
    DISPLAY '果物2   : ' WS-FRUIT-2.
    DISPLAY '果物3   : ' WS-FRUIT-3.
    DISPLAY '果物4   : ' WS-FRUIT-4.

    STOP RUN.

ソースコードの表示結果

分割前データ: Apple/Banana,Orange Mango
--- 分割後 ---
果物1   : Apple
果物2   : Banana
果物3   : Orange
果物4   : Mango

スラッシュ、カンマ、スペースのどれが現れても、そこで区切ってくれているのがわかりますね!

分割後の格納先を複数指定する (INTO句)

INTO句には、分割したデータを入れたい項目を、入れたい順番にカンマで区切って指定します。

例えば、INTO WS-ITEM-A, WS-ITEM-B, WS-ITEM-C と書けば、分割された1番目のデータが WS-ITEM-A に、2番目が WS-ITEM-B に、3番目が WS-ITEM-C に入ります。

ここで気になるのが、「分割された数」と「INTOで指定した数」が違ったらどうなるの?という点ですよね。

  • 分割された数 < INTOで指定した数 の場合
    余ったINTOの項目には、何も格納されません(通常は初期値のままか、スペースなどで埋められます)。
  • 分割された数 > INTOで指定した数 の場合
    INTOで指定した項目数までしか格納されず、入りきらなかったデータは捨てられてしまいます。これは意図しないデータ欠損につながる可能性があるので注意が必要です。

格納先の項目は、分割されるデータの最大長を考慮して、十分な桁数(PIC)を確保しておくのが基本です。

*> 例:分割されるデータよりINTO句の項目が少ない
IDENTIFICATION DIVISION.
PROGRAM-ID. UNSTRING-INTO-FEW.

DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-INPUT          PIC X(20) VALUE 'A,B,C,D,E'.
01 WS-OUT-1          PIC X(5).
01 WS-OUT-2          PIC X(5).

PROCEDURE DIVISION.
    INITIALIZE WS-OUT-1 WS-OUT-2. *> 初期化しておく

    UNSTRING WS-INPUT
        DELIMITED BY ','
        INTO WS-OUT-1, WS-OUT-2 *> 2つしか指定しない
    END-UNSTRING.

    DISPLAY 'OUT-1: ' WS-OUT-1.
    DISPLAY 'OUT-2: ' WS-OUT-2. *> C,D,Eは格納されない

    STOP RUN.

この例だと、WS-OUT-1に'A'、WS-OUT-2に'B'が入り、'C','D','E'はどこにも格納されません。

分割位置を制御する (WITH POINTER句)

WITH POINTER句を使うと、UNSTRING文が文字列のどこから分割処理を開始するかを指定したり、どこまで処理が進んだかを知ったりできます。

これを使うには、まず作業領域(WORKING-STORAGE SECTION)に、ポインター用の数字項目(例えば WS-POINTER PIC 9(3) のように)を用意します。

UNSTRING文を実行する前に、このポインター変数に開始したい位置(通常は1)を設定しておきます。

UNSTRING文が実行されると、指定した位置から分割が始まり、処理が進むにつれてポインター変数の値も増えていきます。そして、UNSTRING文が終わったとき、ポインター変数は「次に処理を開始するべき位置」を指しています。

これを利用すると、例えば、一度のUNSTRING文では分割しきれないほど長いデータを、ループ処理で少しずつ分割していく、といった応用が可能になります。

ソースコード

IDENTIFICATION DIVISION.
PROGRAM-ID. UNSTRING-POINTER.

DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-INPUT-DATA      PIC X(30) VALUE 'ITEM1,ITEM2,ITEM3,ITEM4'.
01 WS-ITEM            PIC X(10).
01 WS-POINTER         PIC 9(3).  *> ポインター用変数

PROCEDURE DIVISION.
    MOVE 1 TO WS-POINTER. *> 開始位置を1に設定

    DISPLAY '--- 1回目のUNSTRING ---'.
    UNSTRING WS-INPUT-DATA
        DELIMITED BY ','
        INTO WS-ITEM
        WITH POINTER WS-POINTER *> ポインターを指定
    END-UNSTRING.
    DISPLAY '取得ITEM: ' WS-ITEM.
    DISPLAY 'POINTER位置: ' WS-POINTER. *> 処理が進んだ位置が表示される

    DISPLAY '--- 2回目のUNSTRING ---'.
    UNSTRING WS-INPUT-DATA
        DELIMITED BY ','
        INTO WS-ITEM
        WITH POINTER WS-POINTER *> 前回の続きから開始
    END-UNSTRING.
    DISPLAY '取得ITEM: ' WS-ITEM.
    DISPLAY 'POINTER位置: ' WS-POINTER.

    STOP RUN.

ソースコードの表示結果

--- 1回目のUNSTRING ---
取得ITEM: ITEM1
POINTER位置: 007  *> ITEM1と,の次の位置
--- 2回目のUNSTRING ---
取得ITEM: ITEM2
POINTER位置: 013  *> ITEM2と,の次の位置

1回目のUNSTRINGが終わった後、WS-POINTERが次の開始位置(7文字目)を指しているので、そのまま2回目のUNSTRINGを実行すると、ちゃんとITEM2から処理が始まっているのがわかりますね。ポインター変数の初期化(最初に1を入れるなど)を忘れないのがコツです。

分割した項目数をカウントする (TALLYING IN句)

TALLYING IN句を使うと、そのUNSTRING文で実際にいくつの項目がINTO句の変数に格納されたかを数えることができます。

これも、カウント結果を格納するための数字項目(例えば WS-COUNT PIC 9(3) のように)を作業領域に用意して使います。

UNSTRING文が実行されると、分割して格納した項目の数が、このカウント用変数に自動的にセットされます。

分割されるデータの項目数が毎回変わるような場合に、後続の処理(例えば、取得した項目数だけループするなど)を制御するのに便利です。また、想定通りの数だけ分割できたかを確認するのにも使えますね。

ソースコード

IDENTIFICATION DIVISION.
PROGRAM-ID. UNSTRING-TALLYING.

DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-INPUT-DATA      PIC X(30) VALUE 'A,B,C'.
01 WS-ITEM-1          PIC X(5).
01 WS-ITEM-2          PIC X(5).
01 WS-ITEM-3          PIC X(5).
01 WS-ITEM-4          PIC X(5). *> 使われない格納先
01 WS-COUNT           PIC 9(3).  *> カウント用変数

PROCEDURE DIVISION.
    INITIALIZE WS-ITEM-1 WS-ITEM-2 WS-ITEM-3 WS-ITEM-4.
    MOVE 0 TO WS-COUNT. *> カウント変数を初期化

    UNSTRING WS-INPUT-DATA
        DELIMITED BY ','
        INTO WS-ITEM-1, WS-ITEM-2, WS-ITEM-3, WS-ITEM-4
        TALLYING IN WS-COUNT *> 格納数をカウント
    END-UNSTRING.

    DISPLAY 'ITEM-1: ' WS-ITEM-1.
    DISPLAY 'ITEM-2: ' WS-ITEM-2.
    DISPLAY 'ITEM-3: ' WS-ITEM-3.
    DISPLAY 'ITEM-4: ' WS-ITEM-4. *> ここは空のはず
    DISPLAY '格納された項目数: ' WS-COUNT. *> 3 が表示されるはず

    STOP RUN.

ソースコードの表示結果

ITEM-1: A
ITEM-2: B
ITEM-3: C
ITEM-4:
格納された項目数: 003

ちゃんと、実際に格納された項目数「3」が WS-COUNT に入っていますね。TALLYINGで使う変数も、実行前に0などで初期化しておくのがお作法です。

COBOL「UNSTRING文」を使う上での注意点

便利なUNSTRING文ですが、いくつか気をつけておきたいポイントがあります。思わぬエラーやデータの食い違いを防ぐために、頭の片隅に入れておいてくださいね。

  • 格納先項目の桁あふれ (OVERFLOW)
    分割されたデータが、INTO句で指定した格納先項目(PIC X(5)など)の桁数より長かった場合、基本的にはデータが途中でちょん切れてしまいます。全部ちゃんと入るように、格納先の桁数は余裕をもって定義しましょう。
    ON OVERFLOW句を指定しておくと、桁あふれが発生した場合に特別な処理(エラーメッセージを出すなど)を実行させることも可能です。
  • 区切り文字が見つからない
    DELIMITED BYで指定した区切り文字が、分割対象の文字列中に一つも見つからなかった場合、分割は行われず、INTO句の最初の項目に元の文字列全体が(格納先の桁数分だけ)コピーされる、といった挙動になることが多いです。意図しない結果になる可能性があるので注意しましょう。
  • POINTER変数・TALLYING変数の初期化
    WITH POINTER句やTALLYING IN句を使う場合、UNSTRING文を実行する前に、必ずそれぞれの変数を適切な値(POINTERなら通常1、TALLYINGなら0)に初期化(MOVE命令などで値を設定)しましょう。初期化を忘れると、前の処理で使われた値が残っていて、予期せぬ動きをする原因になります。
  • 項目の属性
    UNSTRING文は基本的に文字列を扱います。分割元のデータも、格納先の項目も、通常は文字タイプ(PIC X)で定義します。数字として扱いたい場合でも、一度PIC Xで受け取ってから、後で数字項目(PIC 9)に転記・変換するのが安全です。
  • END-UNSTRINGの書き忘れ
    UNSTRING文の終わりには、END-UNSTRINGを書くのを忘れずに。書き忘れるとコンパイルエラーになったり、意図しない範囲までUNSTRING文の影響が及んだりすることがあります。

これらの点に気をつければ、UNSTRING文はあなたの強力な味方になってくれますよ!

【まとめ】COBOLの「UNSTRING文」をマスターして効率的なデータ処理を

今回は、COBOLのUNSTRING文について、基本的な考え方から具体的な使い方、そして注意点まで、サンプルコードを交えながら解説してきました。

UNSTRING文は、カンマ区切りやスペース区切りなどのデータを扱う際に、文字列を効率よく分割・整理するための非常に便利な命令です。

DELIMITED BY で区切り方を指定し、INTO で格納先を指定するのが基本。さらに WITH POINTERTALLYING IN などのオプションを使えば、より複雑なデータ処理にも対応できます。

最初は少しとっつきにくい部分もあるかもしれませんが、この記事で紹介したサンプルコードなどを参考に、実際に手を動かして試してみるのが一番の近道です。

UNSTRING文を使いこなせるようになれば、COBOLでのデータ加工やファイル処理の幅がぐっと広がります。ぜひ、あなたのCOBOLスキルの一つとして、自信を持って活用していってくださいね!応援しています!

【関連記事】

>> 今さら聞けない「COBOLとは?」

このブログを検索

  • ()

自己紹介

自分の写真
リモートワークでエンジニア兼Webディレクターとして活動しています。プログラミングやAIなど、日々の業務や学びの中で得た知識や気づきをわかりやすく発信し、これからITスキルを身につけたい人にも役立つ情報をお届けします。 note → https://note.com/yurufuri X → https://x.com/mnao111

QooQ