SEPARATE

SEPARATE

operand1

SUBSTRING (operand1,operand2,operand3)
  [[STARTING] FROM [POSITION] operand8]  
  [LEFT [JUSTIFIED]] INTOoperand4
 

IGNORE

 
  REMAINDERoperand5
REMAINDER POSITION operand9
 

WITH [RETAINED]

[ANY] DELIMITERS
  INPUT DELIMITERS
  DELIMITERS operand6
  [[GIVING] NUMBER [INoperand7]

このドキュメントでは、次のトピックについて説明します。

構文図で使用されている記号については、「構文記号」を参照してください。

関連ステートメント: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
ソースオペランド:

operand1 は、内容を分割する英数字/バイナリの定数または変数です。

operand1 内の末尾の空白は、その値が処理される前に削除されます(デリミタ文字として空白を使用する場合でも同様です。DELIMITERS オプションも参照)。

SUBSTRING
SUBSTRING オプション:

通常、フィールドの内容全体が先頭から分割されます。

SUBSTRING オプションでは、フィールドの一部だけを分割できます。SUBSTRING 節のフィールド名(operand1)の後に、まず開始位置(operand2)、次に分割するフィールド部分の長さ(operand3)を指定します。例えば、CONTRAPTION が含まれるフィールド #A の場合、SUBSTRING(#A,5,3) には RAP が含まれます。

注意:
operand2 を省略すると、開始位置は 1 とみなされます。operand3 を省略すると、長さはフィールドの開始位置から終わりまでとみなされます。

STARTING FROM POSITION operand8
STARTING FROM POSITION オプション:

このオプションでは、分割するソースオペランド(operand1)の開始位置を決定します。

詳細については、「STARTING POSITION の範囲の定義」を参照してください。

LEFT JUSTIFIED
LEFT JUSTIFIED オプション:

このオプションでは、ターゲットオペランドからデリミタ文字と次の空白以外の文字の間に存在する先頭の空白を削除します。

operand4
ターゲットオペランド:

operand4 は、ターゲットオペランドを表します。ターゲットオペランドとして配列が指定されている場合、分割された値は各オカレンスに送られます。

ターゲットオペランドの個数は、operand1 内のデリミタ文字(末尾のデリミタ文字を含む)の個数に 1 を加えたものに相当します。

operand4 がダイナミック変数のとき、その長さは SEPARATE 操作によって変更できます。ダイナミック変数の現在の長さは、システム変数 *LENGTH を使用して確認できます。

ダイナミック変数に関する全般的な情報については、「ダイナミック変数およびラージ変数の使用」を参照してください。

IGNORE /

REMAINDER operand5

IGNORE/REMAINDER オプション:

分割されたソース値を受け取るターゲットフィールドが足りないと、該当するエラーメッセージが返されます。

これを避けるために、次の 2 つのオプションを使用できます。

  • IGNORE オプション:

    IGNORE を指定すると、Natural はソース値を受け取るターゲットオペランドが足りない場合はそれを無視します。

  • REMAINDER オプション:

    REMAINDER operand5 を指定すると、ターゲットオペランドに挿入できなかったソース値は operand5 に挿入されます。operand5 の内容は、後続の SEPARATE ステートメントなどの処理に使用できます。

    REMAINDER は、単一値のソースオペランドにのみ使用できます。配列ソースオペランドの場合は、REMAINDER POSITION オプションを使用します。

ルールと操作上の考慮事項」および「例 3」も参照してください。

REMAINDER POSITION operand9
REMAINDER POSITION オプション:

REMAINDER POSITION 節から返された値は、REMAINDER データフィールドの入力開始位置に対応します。

詳細については、「ルールと操作上の考慮事項」を参照してください。

DELIMITERS
DELIMITERS オプション:

下記の「DELIMITERS オプション」を参照してください。

RETAINED
RETAINED オプション:

通常、デリミタ文字自体はターゲットオペランドには移されません。

RETAINEDを指定すると、デリミタ(デフォルトのデリミタや空白、あるいは operand6 で指定されたデリミタ)もターゲットオペランドに挿入されます。

例:

次の SEPARATE ステートメントでは、150#B+#C30#D に挿入しています。

...
MOVE '150+30' TO #A
SEPARATE #A INTO #B #C #D WITH RETAINED DELIMITER '+'
...

例 3」も参照してください。

GIVING NUMBER operand7
GIVING NUMBER オプション:

このオプションでは、値(空白で返されたものも含む)が挿入されたターゲットオペランドの個数を operand7 に返します。実際に得られる数はデリミタ文字の個数に 1 を加えたものです。

IGNORE オプションを使用した場合、operand7 に返される有効な最大数はターゲットオペランド(operand4)の個数です。

REMAINDER オプションを使用した場合、operand7 に返される有効な最大数はターゲットオペランド(operand4)の個数に operand5 を加えたものです。

DELIMITERS オプション:

operand1 内のデリミタ文字は、値を分割する位置を示します。

構文要素の説明:

構文要素 説明
WITH [ANY] DELIMITERS DELIMITERS オプションを省略した場合、または WITH ANY DELIMITERS を指定した場合は、空白、および英字や数字以外の任意の文字がデリミタ文字として扱われます。
WITH INPUT DELIMITERS 空白およびデフォルトの入力デリミタ文字(セッションパラメータ ID で指定)がデリミタ文字として使用されることを示します。
WITH DELIMITERS operand6 operand6 で指定した各文字がデリミタ文字として使用されることを示します。

operand6 に含まれる末尾の空白は無視されます。

ルールと操作上の考慮事項

ソースオペランドおよびターゲットオペランドの処理

分割処理が開始されると、ソースオペランド(単一値および配列オカレンスでも)の末尾の空白は無視されます。末尾の空白は、REMAINDER POSITION 値が計算された場合にのみカウントされます。「REMAINDER POSITION から返される値」も参照してください。

ソースオペランド(operand1)が空のダイナミックフィールド(*LENGTH=0)または展開されていない X-array の場合、次のフィールドをリセットすると SEPARATE ステートメントの実行が停止します。

  • すべてのターゲットオペランド(operand4)、

  • 値が挿入されたターゲットオペランドの個数を返すフィールド(operand7)、

  • REMAINDER データフィールド(operand5)、

  • REMAINDER POSITION フィールド(operand9

ソースオペランドに空白のみが含まれている場合も同様です。

STARTING FROM POSITION の範囲の定義

STARTING FROM POSITIONoperand8 に使用できる値の範囲は 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 (1:5) DYNAMIC
*LENGTH(#D(*)) = (15,25,0,33,61)

は、#D(4) の 23 番目の文字です。

無効な範囲(負またはゼロの値、あるいは実際のフィールド長よりも大きい値)を指定した場合、「ソースオペランドおよびターゲットオペランドの処理」に記載された戻りフィールドはリセットされますが、ランタイムエラーは発生しません。STARTING FROM 値は(オフセットではなく)位置を示すため、operand8 では最初の実行時に最小値の 1 が必要です。

REMAINDER POSITION から返される値

REMAINDER POSITION 節から返された値は、REMAINDER データフィールドの入力開始位置に対応します。

例:

...
SEPARATE 'AB  CD' INTO #A REMAINDER #R
...

上記のステートメントでは、セパレータ文字(ここでは空白)の後、AB の直後に REMAINDER が開始すると #A= 'AB' および #R= ' CD' が返されます。その代わりに REMAINDER POSITION オプションを使用すると、4 の値が返されます。

分割処理中は末尾の空白は無視されますが、ソース配列のオカレンスの REMAINDER POSITION 値の計算には、末尾の空白が反映されます。

すべてのソースセグメントが処理され、ソースフィールドの末尾に達すると、REMAINDER POSITION は"これ以上データがない"ことを示すゼロを返します。

例 6 - 開始位置と残りの位置を含むソース配列の使用」も参照してください。

重複しているフィールド:REMAINDER および REMAINDER POSITION

SEPARATE ステートメントが実行されると、通常はソースデータ(operand1)がコピーされ、作業フィールドから処理されます。したがって、REMAINDER の結果はソースフィールドと結果フィールドの重複の影響を受けません。

このようなフィールドバックアップコピーは、REMAINDER POSITION 節が使用されている場合は生成されません。ソースオペランドとターゲットオペランドを分割するかどうかにかかわらず、全分割プロセスが元のソースオペランドで実行されます。オペランドが重複している場合は、コンパイル時や実行時に拒否されませんが、望ましくない結果が生じる可能性があります。

SEPARATE のデリミタ

単一値のフィールドを分割すると、フィールドの境界は常に最後の単語で区切られます。配列フィールドの各オカレンスについても同様です。

RETAINED DELIMITERS オプションを使用する場合、デリミタもターゲットフィールドに配置されます。これは、配列オカレンス内のデリミタ文字にのみ適用され、オカレンス終了時に自動的に区切られた(デリミタ文字を含まない)連続した配列オカレンスには適用されません。

例 4 - 再定義された文字列のソース配列の使用」および「例 5 - RETAINED デリミタを含むソース配列の使用」も参照してください。

例 1 - 各種サンプル

** 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

プログラム SEPEX1 の出力:

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:

例 2 - 配列の使用

** 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

プログラム SEPEX2 の出力:

VALUE1,   VALUE2,VALUE3
                       
VALUE1                 
VALUE2                 
VALUE3                 
                       
                       
  3

例 3 - REMAINDER/RETAINED オプションの使用

** 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

プログラム SEPEX3 の出力:

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

例 4 - 再定義された文字列のソース配列の使用

**  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

プログラム SEPEX4 の出力:

         #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

例 5 - RETAINED デリミタを含むソース配列の使用

**  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

プログラム SEPEX5 の出力:

       #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

例 6 - 開始位置と残りの位置を含むソース配列の使用

**  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

プログラム SEPEX6 の出力:

#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