このドキュメントでは、次のトピックについて説明します。
構文図で使用されている記号については、「構文記号」を参照してください。
関連ステートメント:COMPRESS | COMPUTE | EXAMINE | MOVE | MOVE ALL | RESET
関連機能グループ:算術演算とデータ移動操作
SEPARATE ステートメントは 1 つの英数字またはバイナリオペランドの内容を複数の英数字またはバイナリオペランド(または英数字やバイナリ配列の複数オカレンス)に分割するために使用します。
オペランド定義テーブル:
| オペランド | 構文要素 | フォーマット | オペランド参照 | ダイナミック定義 | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
operand1 |
C | S | A | A | U | B | ○ | × | ||||||||||||
operand2 |
C | S | N | P | I | B * | ○ | × | ||||||||||||
operand3 |
C | S | N | P | I | B * | ○ | × | ||||||||||||
operand4 |
S | A | G | A | U | B | ○ | ○ | ||||||||||||
operand5 |
S | A | U | B | ○ | ○ | ||||||||||||||
operand6 |
C | S | A | U | B | ○ | × | |||||||||||||
operand7 |
S | N | P | I | ○ | ○ | ||||||||||||||
operand8 |
C | S | N | P | I | ○ | × | |||||||||||||
operand9 |
S | N | P | I | ○ | ○ | ||||||||||||||
* operand2 および operand3 のフォーマット B は、4 以下の長さでのみ使用できます。
構文要素の説明:
| 構文要素 | 説明 |
|---|---|
operand1 |
ソースオペランド:
|
SUBSTRING |
SUBSTRING オプション:
通常、フィールドの内容全体が先頭から分割されます。
注意: |
STARTING FROM POSITION
operand8 |
STARTING FROM POSITION オプション:
このオプションでは、分割するソースオペランド( 詳細については、「STARTING POSITION の範囲の定義」を参照してください。 |
LEFT JUSTIFIED |
LEFT JUSTIFIED オプション:
このオプションでは、ターゲットオペランドからデリミタ文字と次の空白以外の文字の間に存在する先頭の空白を削除します。 |
operand4 |
ターゲットオペランド:
ターゲットオペランドの個数は、
ダイナミック変数に関する全般的な情報については、「ダイナミック変数およびラージ変数の使用」を参照してください。 |
IGNORE /
|
IGNORE/REMAINDER オプション:
分割されたソース値を受け取るターゲットフィールドが足りないと、該当するエラーメッセージが返されます。 これを避けるために、次の 2 つのオプションを使用できます。
「ルールと操作上の考慮事項」および「例 3」も参照してください。 |
REMAINDER POSITION
operand9 |
REMAINDER POSITION オプション:
詳細については、「ルールと操作上の考慮事項」を参照してください。 |
DELIMITERS |
DELIMITERS オプション:
下記の「DELIMITERS オプション」を参照してください。 |
RETAINED |
RETAINED オプション:
通常、デリミタ文字自体はターゲットオペランドには移されません。
例: 次の ... MOVE '150+30' TO #A SEPARATE #A INTO #B #C #D WITH RETAINED DELIMITER '+' ... 「例 3」も参照してください。 |
GIVING NUMBER
operand7 |
GIVING NUMBER オプション:
このオプションでは、値(空白で返されたものも含む)が挿入されたターゲットオペランドの個数を IGNORE オプションを使用した場合、 REMAINDER オプションを使用した場合、 |
operand1 内のデリミタ文字は、値を分割する位置を示します。
構文要素の説明:
| 構文要素 | 説明 |
|---|---|
WITH [ANY]
DELIMITERS |
DELIMITERS オプションを省略した場合、または WITH ANY DELIMITERS を指定した場合は、空白、および英字や数字以外の任意の文字がデリミタ文字として扱われます。
|
WITH INPUT
DELIMITERS |
空白およびデフォルトの入力デリミタ文字(セッションパラメータ ID で指定)がデリミタ文字として使用されることを示します。
|
WITH
DELIMITERS operand6 |
operand6 で指定した各文字がデリミタ文字として使用されることを示します。
|
分割処理が開始されると、ソースオペランド(単一値および配列オカレンスでも)の末尾の空白は無視されます。末尾の空白は、REMAINDER POSITION 値が計算された場合にのみカウントされます。「REMAINDER POSITION から返される値」も参照してください。
ソースオペランド(operand1)が空のダイナミックフィールド(*LENGTH=0)または展開されていない X-array の場合、次のフィールドをリセットすると SEPARATE ステートメントの実行が停止します。
すべてのターゲットオペランド(operand4)、
値が挿入されたターゲットオペランドの個数を返すフィールド(operand7)、
REMAINDER データフィールド(operand5)、
REMAINDER POSITION フィールド(operand9)
ソースオペランドに空白のみが含まれている場合も同様です。
STARTING FROM POSITION 節 operand8 に使用できる値の範囲は 1:n です。ここで、n はソースフィールドの最後のバイトです。
ソースオペランド(operand1)が配列の場合、末尾の空白を含むすべてのオカレンスがカウントされます。ダイナミック配列では、指定した位置まで個々のフィールドの長さがカウントされます。
operand8 の例:
位置 63:#A (A100) |
は、#A.の 63 番目の文字です。
|
位置 63:#B
(A20/1:10) |
は、#B(4) の 3 番目の文字です。
|
位置 63:#C
(A10/1:3,1:4) |
は、#C(2,3) の 3 番目の文字です。
|
|
位置 63: |
は、#D(4) の 23 番目の文字です。
|
無効な範囲(負またはゼロの値、あるいは実際のフィールド長よりも大きい値)を指定した場合、「ソースオペランドおよびターゲットオペランドの処理」に記載された戻りフィールドはリセットされますが、ランタイムエラーは発生しません。STARTING FROM 値は(オフセットではなく)位置を示すため、operand8 では最初の実行時に最小値の 1 が必要です。
REMAINDER POSITION 節から返された値は、REMAINDER データフィールドの入力開始位置に対応します。
例:
... SEPARATE 'AB CD' INTO #A REMAINDER #R ...
上記のステートメントでは、セパレータ文字(ここでは空白)の後、AB の直後に REMAINDER が開始すると #A= 'AB' および #R= '
CD' が返されます。その代わりに REMAINDER
POSITION オプションを使用すると、4 の値が返されます。
分割処理中は末尾の空白は無視されますが、ソース配列のオカレンスの REMAINDER
POSITION 値の計算には、末尾の空白が反映されます。
すべてのソースセグメントが処理され、ソースフィールドの末尾に達すると、REMAINDER POSITION は"これ以上データがない"ことを示すゼロを返します。
「例 6 - 開始位置と残りの位置を含むソース配列の使用」も参照してください。
SEPARATE ステートメントが実行されると、通常はソースデータ(operand1)がコピーされ、作業フィールドから処理されます。したがって、REMAINDER の結果はソースフィールドと結果フィールドの重複の影響を受けません。
このようなフィールドバックアップコピーは、REMAINDER
POSITION 節が使用されている場合は生成されません。ソースオペランドとターゲットオペランドを分割するかどうかにかかわらず、全分割プロセスが元のソースオペランドで実行されます。オペランドが重複している場合は、コンパイル時や実行時に拒否されませんが、望ましくない結果が生じる可能性があります。
単一値のフィールドを分割すると、フィールドの境界は常に最後の単語で区切られます。配列フィールドの各オカレンスについても同様です。
RETAINED DELIMITERS オプションを使用する場合、デリミタもターゲットフィールドに配置されます。これは、配列オカレンス内のデリミタ文字にのみ適用され、オカレンス終了時に自動的に区切られた(デリミタ文字を含まない)連続した配列オカレンスには適用されません。
「例 4 - 再定義された文字列のソース配列の使用」および「例 5 - RETAINED デリミタを含むソース配列の使用」も参照してください。
** Example 'SEPEX1': SEPARATE
************************************************************************
DEFINE DATA LOCAL
1 #TEXT1 (A6) INIT <'AAABBB'>
1 #TEXT2 (A7) INIT <'AAA BBB'>
1 #TEXT3 (A7) INIT <'AAA-BBB'>
1 #TEXT4 (A7) INIT <'A.B/C,D'>
1 #FIELD1A (A6)
1 #FIELD1B (A6)
1 #FIELD2A (A3)
1 #FIELD2B (A3)
1 #FIELD3A (A3)
1 #FIELD3B (A3)
1 #FIELD4A (A3)
1 #FIELD4B (A3)
1 #FIELD4C (A3)
1 #FIELD4D (A3)
1 #NBT (N1)
1 #DEL (A5)
END-DEFINE
*
WRITE NOTITLE 'EXAMPLE A (SOURCE HAS NO BLANKS)'
SEPARATE #TEXT1 INTO #FIELD1A #FIELD1B GIVING NUMBER #NBT
WRITE / '=' #TEXT1 5X '=' #FIELD1A 4X '=' #FIELD1B 4X '=' #NBT
*
WRITE NOTITLE /// 'EXAMPLE B (SOURCE HAS EMBEDDED BLANK)'
SEPARATE #TEXT2 INTO #FIELD2A #FIELD2B GIVING NUMBER #NBT
WRITE / '=' #TEXT2 4X '=' #FIELD2A 7X '=' #FIELD2B 7X '=' #NBT
*
WRITE NOTITLE /// 'EXAMPLE C (USING DELIMITER ''-'')'
SEPARATE #TEXT3 INTO #FIELD3A #FIELD3B WITH DELIMITER '-'
WRITE / '=' #TEXT3 4X '=' #FIELD3A 7X '=' #FIELD3B
*
MOVE ',/' TO #DEL
WRITE NOTITLE /// 'EXAMPLE D USING DELIMITER' '=' #DEL
*
SEPARATE #TEXT4 INTO #FIELD4A #FIELD4B
#FIELD4C #FIELD4D WITH DELIMITER #DEL
WRITE / '=' #TEXT4 4X '=' #FIELD4A 7X '=' #FIELD4B
/ 19X '=' #FIELD4C 7X '=' #FIELD4D
*
END
EXAMPLE A (SOURCE HAS NO BLANKS)
#TEXT1: AAABBB #FIELD1A: AAABBB #FIELD1B: #NBT: 1
EXAMPLE B (SOURCE HAS EMBEDDED BLANK)
#TEXT2: AAA BBB #FIELD2A: AAA #FIELD2B: BBB #NBT: 2
EXAMPLE C (USING DELIMITER '-')
#TEXT3: AAA-BBB #FIELD3A: AAA #FIELD3B: BBB
EXAMPLE D USING DELIMITER #DEL: ,/
#TEXT4: A.B/C,D #FIELD4A: A.B #FIELD4B: C
#FIELD4C: D #FIELD4D:
** Example 'SEPEX2': SEPARATE (using array variable)
************************************************************************
DEFINE DATA LOCAL
1 #INPUT-LINE (A60) INIT <'VALUE1, VALUE2,VALUE3'>
1 #FIELD (A20/1:5)
1 #NUMBER (N2)
END-DEFINE
*
SEPARATE #INPUT-LINE LEFT JUSTIFIED INTO #FIELD (1:5)
GIVING NUMBER IN #NUMBER
*
WRITE NOTITLE #INPUT-LINE //
#FIELD (1) /
#FIELD (2) /
#FIELD (3) /
#FIELD (4) /
#FIELD (5) /
#NUMBER
*
END
VALUE1, VALUE2,VALUE3
VALUE1
VALUE2
VALUE3
3
** Example 'SEPEX3': SEPARATE (with REMAINDER, RETAIN option)
************************************************************************
DEFINE DATA LOCAL
1 #INPUT-LINE (A60) INIT <'VAL1, VAL2, VAL3,VAL4'>
1 #FIELD (A10/1:4)
1 #REM (A30)
END-DEFINE
*
WRITE TITLE LEFT 'INP:' #INPUT-LINE /
'#FIELD (1)' 13T '#FIELD (2)' 25T '#FIELD (3)'
37T '#FIELD (4)' 49T 'REMAINDER'
/ '----------' 13T '----------' 25T '----------'
37T '----------' 49T '------------------------------'
*
SEPARATE #INPUT-LINE INTO #FIELD (1:2)
REMAINDER #REM WITH DELIMITERS ','
WRITE #FIELD(1) 13T #FIELD(2) 25T #FIELD(3) 37T #FIELD(4) 49T #REM
*
RESET #FIELD(*) #REM
SEPARATE #INPUT-LINE INTO #FIELD (1:2)
IGNORE WITH DELIMITERS ','
WRITE #FIELD(1) 13T #FIELD(2) 25T #FIELD(3) 37T #FIELD(4) 49T #REM
*
RESET #FIELD(*) #REM
SEPARATE #INPUT-LINE INTO #FIELD (1:4) IGNORE
WITH RETAINED DELIMITERS ','
WRITE #FIELD(1) 13T #FIELD(2) 25T #FIELD(3) 37T #FIELD(4) 49T #REM
*
RESET #FIELD(*) #REM
*
SEPARATE SUBSTRING(#INPUT-LINE,1,50) INTO #FIELD (1:4)
IGNORE WITH DELIMITERS ','
WRITE #FIELD(1) 13T #FIELD(2) 25T #FIELD(3) 37T #FIELD(4) 49T #REM
*
END
INP: VAL1, VAL2, VAL3,VAL4 #FIELD (1) #FIELD (2) #FIELD (3) #FIELD (4) REMAINDER ---------- ---------- ---------- ---------- ------------------------------ VAL1 VAL2 VAL3,VAL4 VAL1 VAL2 VAL1 , VAL2 , VAL1 VAL2 VAL3 VAL4
** Example 'SEPEX4': SEPARATE with source array ************************************************************************ * This example shows different results when separating a scalar string * or a string array redefining the scalar string. * * ************************************************************************ * * DEFINE DATA LOCAL 1 #TEXT (A24) INIT <'VAL1 VAL2 VAL3 VAL4 VAL5'> 1 REDEFINE #TEXT 2 #TEXTARRAY (A12/2) 1 #WORD1(A5/6) 1 #WORD2(A5/6) END-DEFINE * SEPARATE #TEXT INTO #WORD1(*) /* Redefinition may split original words into two parts SEPARATE #TEXTARRAY(*) INTO #WORD2(*) * DISPLAY #TEXT #WORD1(*) #TEXTARRAY(*) #WORD2(*) END
#TEXT #WORD1 #TEXTARRAY #WORD2
------------------------ ------ ------------ ------
VAL1 VAL2 VAL3 VAL4 VAL5 VAL1 VAL1 VAL2 VA VAL1
VAL2 L3 VAL4 VAL5 VAL2
VAL3 VA
VAL4 L3
VAL5 VAL4
VAL5
** Example 'SEPEX5': SEPARATE with and without RETAINED DELIMITERS
***********************************************************************
* This example shows different results with a source array
* when using the option RETAINED DELIMITERS or not.
*
*
***********************************************************************
*
*
DEFINE DATA LOCAL
1 #TEXT(A20) INIT <'VAL1,VAL2,VAL3,VAL4'>
1 #TEXTARRAY(A10/3) INIT <'VAL1,VAL2',
'VAL3',
'VAL4'>
1 #WORD1(A5/7)
1 #WORD2(A5/7)
END-DEFINE
*
SEPARATE #TEXT INTO #WORD1(*)
SEPARATE #TEXTARRAY(*) INTO #WORD2(*)
DISPLAY #TEXT #WORD1(*) #TEXTARRAY(*) #WORD2(*)
*
SEPARATE #TEXT INTO #WORD1(*) WITH RETAINED DELIMITERS
SEPARATE #TEXTARRAY(*) INTO #WORD2(*) WITH RETAINED DELIMITERS
DISPLAY #TEXT #WORD1(*) #TEXTARRAY(*) #WORD2(*)
*
END
#TEXT #WORD1 #TEXTARRAY #WORD2
-------------------- ------ ---------- ------
VAL1,VAL2,VAL3,VAL4 VAL1 VAL1,VAL2 VAL1
VAL2 VAL3 VAL2
VAL3 VAL4 VAL3
VAL4 VAL4
VAL1,VAL2,VAL3,VAL4 VAL1 VAL1,VAL2 VAL1
, VAL3 ,
VAL2 VAL4 VAL2
, VAL3
VAL3 VAL4
,
VAL4
** Example 'SEPEX6': SEPARATE with STARTING FROM and REMAINDER POSITION
************************************************************************
* This example shows how the options STARTING FROM POSITION and
* REMAINDER POSITION work together in a processing loop when
* separating a source array.
*
************************************************************************
*
*
DEFINE DATA LOCAL
1 #TEXT (A15/1:3) INIT <'VAL1 VAL2',
'VAL3',
'VAL4 VAL5 VAL6'>
1 #WORD (A5/1:4)
1 #POS (I1) INIT <1>
END-DEFINE
*
WRITE '#TEXT(A15/1:3): (1) (2) (3)'
/ 16T #TEXT(*)
/ 16T '----+----1----+ ----2----+----3 ----+----4----+'
// '#WORD (A5/1:4): (1) (2) (3) (4) : #POS'
'(within #TEXT(*))'
*
REPEAT
SEPARATE #TEXT(*) STARTING FROM POSITION #POS
INTO #WORD(*) REMAINDER POSITION #POS
WRITE 16T #WORD(*) 44T ': ' #POS
UNTIL #POS = 0
END-REPEAT
END
#TEXT(A15/1:3): (1) (2) (3)
VAL1 VAL2 VAL3 VAL4 VAL5 VAL6
----+----1----+ ----2----+----3 ----+----4----+
#WORD (A5/1:4): (1) (2) (3) (4) : #POS (within #TEXT(*))
VAL1 VAL2 VAL3 VAL4 : 36
VAL5 VAL6 : 0