2016-03-28 28 views
1

Iは、文字列区切り文字で区切られた文字列をどのように抽出するか?

v-edistring = "STS++56+202:::DUE TO HOLIDAY1'STS++56+202:::DUE TO HOLIDAY2'STS++56+202:::DUE TO HOLIDAY3'" 

アポストロフィ( ')は各ラインセグメントである、行の終了を示しています。私は各セグメントを抽出し、それを変数セグメントに割り当てました。

各セグメントについて、要素(STS、56、202、DUE TO HOLIDAY1)などを順に検索するためにループする必要があります。

DEFINE VARIABLE v-edistring AS CHARACTER NO-UNDO. 
DEFINE VARIABLE v-cnt AS INTEGER  NO-UNDO. 
DEFINE VARIABLE segment AS CHARACTER NO-UNDO. 

v-edistring = "STS++56+202:::DUE TO HOLIDAY1'STS++56+202:::DUE TO HOLIDAY2'STS++56+202:::DUE TO HOLIDAY3'". 

DO v-cnt = 1 TO num-entries(v-edistring, "'") - 1 : 

    ASSIGN segment = string(entry(v-cnt, v-edistring, "'")). 

    MESSAGE segment 
     VIEW-AS ALERT-BOX INFO BUTTONS OK. 

    /* FOR EACH segment */ 
    /*DO: 

    alert STS then alert 56 then 202 then due to holiday (ie loop for elements) 

    END. */ 
END. 

答えて

0

これは非常にエレガントではないと私はあなたが暗示として、あなたの区切り文字が一致しているが、ここであなたが行くと仮定...

DEF VAR iCnt  AS INT NO-UNDO. 
DEF VAR ediString AS CHAR NO-UNDO. 
DEF VAR segment AS CHAR NO-UNDO. 
DEF VAR iLoop  AS INT NO-UNDO. 
DEF VAR iLoop2  AS INT NO-UNDO. 
DEF VAR cSubString AS CHAR NO-UNDO. 
DEF VAR cSubString2 AS CHAR NO-UNDO. 
DEF VAR cValue  AS CHAR NO-UNDO. 
DEF VAR iEntry  AS INT NO-UNDO. 
DEF TEMP-TABLE fred 
    FIELD ParentID AS INT 
    FIELD STRINGID AS INT 
    FIELD ParseID AS INT 
    Field ParseValue AS CHAR FORMAT "X(20)". 
ediString = "STS++56+202:::DUE TO HOLIDAY1'STS++56+202:::DUE TO HOLIDAY2'STS++56+202:::DUE TO HOLIDAY3'". 

FUNCTION getEntry RETURNS INT(): 
    iEntry = iEntry + 1. 
    RETURN iEntry. 
END. 

DO iCnt = 1 TO num-entries(ediString, "'") - 1 : 

    ASSIGN segment = string(entry(iCnt, ediString, "'")) 
      iEntry = 0. 
    REPEAT iLoop = 1 TO NUM-ENTRIES(segment,"+"): 


    cSubString = ENTRY(iLoop,segment,"+"). 

    IF cSubString MATCHES "*:*" THEN 
    DO: 

     REPEAT iLoop2 = 1 TO NUM-ENTRIES(cSubString,":"): 

     cSubString2 = ENTRY(iLoop2,cSubString,":"). 

     if cSubString2 = "" THEN NEXT. 
     CREATE fred. 
     ASSIGN 
      fred.ParentID = iCnt 
      fred.StringID = iLoop 
      fred.ParseID = getEntry() 
      fred.parseValue = cSubString2. 
      cSubString2 = "". 

     END. 
    END. 
    ELSE 
    DO: 
    IF cSubString <> "" THEN 
    DO: 
     CREATE fred. 
     ASSIGN 
      fred.ParentID = iCnt 
      fred.StringID = iLoop 
      fred.ParseID = getEntry() 
      fred.ParseValue = cSubString. 
    END. 
    END. 


    END. 
END. 

for each fred: 
    display fred. 
END. 
0

このソリューションは最高、しかし、あなたのパターンを想定しない場合があります私はあなたを助けることができると思った。

DEF TEMP-TABLE tt-data NO-UNDO 
    FIELD sequence  AS INT 
    FIELD string-1  AS CHAR FORMAT 'x(20)' 
    FIELD string-2  AS CHAR FORMAT 'x(20)' 
    FIELD string-3  AS CHAR FORMAT 'x(20)' 
    FIELD string-4  AS CHAR FORMAT 'x(20)' 
    INDEX ch-unique IS PRIMARY UNIQUE 
     sequence. 

DEF VAR i-seq   AS INT NO-UNDO INIT 0. 
DEF VAR c-aux   AS CHAR NO-UNDO EXTENT 4. 
DEF VAR i-count   AS INT NO-UNDO. 
DEF VAR c-source  AS CHAR NO-UNDO. 
DEF VAR c-data   AS CHAR NO-UNDO 
    INIT "STS++56+202:::DUE TO HOLIDAY1'STS++56+202:::DUE TO HOLIDAY2'STS++56+202:::DUE TO HOLIDAY3'". 

DO i-count = 1 TO NUM-ENTRIES(c-data,"'"): 

    ASSIGN c-source = ENTRY(i-count,c-data,"'"). 

    IF TRIM(c-source)    = '' OR 
     NUM-ENTRIES(c-source,'+') <> 4 THEN 
     NEXT. 

    ASSIGN c-aux[1] = ENTRY(1,c-source,'+') 
      c-aux[2] = ENTRY(3,c-source,'+') 
      c-aux[3] = ENTRY(1,ENTRY(4,c-source,'+'),':') 
      c-aux[4] = ENTRY(4,ENTRY(4,c-source,'+'),':'). 

    CREATE tt-data. 
    ASSIGN i-seq    = i-seq + 1 
      tt-data.sequence  = i-seq 
      tt-data.string-1  = c-aux[1] 
      tt-data.string-2  = c-aux[2] 
      tt-data.string-3  = c-aux[3] 
      tt-data.string-4  = c-aux[4]. 

END. 

FOR EACH tt-data 
    BY sequence: 

    DISP tt-data WITH WIDTH 333 NO-ERROR. 

END. 
0

デリミタが2つしかない場合は、このコードを使用して検索を行うことができます。それは3つ以上のデリミタに拡張することができますが、私は多分コードを構造化するでしょう。 (私は区切り文字のリストをループします。そのようなコードが必要な場合は教えてください)

実行する文字列検索の数を最小限に抑えることを目的としています。各検索後に両方の区切り文字を検索するのではなく、1つを検索するだけで十分です。私は、これによって明快さを損なうことなく演技をすることができると信じていますが、私はベンチマーキングを行っていないので、間違っている可能性があります。そして、いつものように、最適なソリューションはデータの性質に依存します。

DEFINE VARIABLE v-edistring AS CHARACTER NO-UNDO. 
DEFINE VARIABLE v-cnt AS INTEGER  NO-UNDO. 
DEFINE VARIABLE segment AS CHARACTER NO-UNDO. 

DEFINE VARIABLE v-curpsn AS INTEGER NO-UNDO. 
DEFINE VARIABLE v-idxplus AS INTEGER NO-UNDO. 
DEFINE VARIABLE v-idxcolon AS INTEGER NO-UNDO. 
DEFINE VARIABLE v-element AS CHARACTER NO-UNDO. 

v-edistring = "STS++56+202:::DUE TO HOLIDAY1'STS++56+202:::DUE TO HOLIDAY2'STS++56+202:::DUE TO HOLIDAY3'". 

DO v-cnt = 1 TO num-entries(v-edistring, "'") - 1 : 

    ASSIGN segment = string(entry(v-cnt, v-edistring, "'")). 

    MESSAGE "SEGMENT: " segment 
     VIEW-AS ALERT-BOX INFO BUTTONS OK. 


    /* 
    ** Cleverness here.... 
    ** Find the first positions of each delimiter in the segment 
    ** 
    ** Then: 
    ** Clip out an element of the segment up through the next nearest delim. 
    ** Recalculate the next postion of that delimiter 
    ** ... and loop 
    */ 
    v-curpsn = 1. 
    v-idxplus = INDEX(segment, "+", v-curpsn). 
    v-idxcolon = INDEX(segment, ":", v-curpsn). 

    DO WHILE TRUE: 

    IF v-idxplus = 0 THEN DO: 
     IF v-idxcolon = 0 THEN LEAVE. /* no more delimiters */ 

     /* Otherwise, next delim is a colon */ 
     v-element = SUBSTRING(segment, v-curPsn, v-idxcolon - v-curPsn). 
     v-curpsn = v-idxcolon + 1. 
     /* No need to recalculate v-idxplus */ 
     v-idxcolon = INDEX(segment, ":", v-curpsn). 

    END. 
    ELSE DO: /* v-idxplus > 0 */ 
     IF v-idxcolon = 0 OR v-idxcolon > v-idxplus THEN DO: 

     /* Either no colons, or next delim is a plus */ 
     v-element = SUBSTRING(segment, v-curPsn, v-idxplus - v-curPsn). 
     v-curpsn = v-idxplus + 1. 
     /* No need to recalculate v-idxcolon */ 
     v-idxplus = INDEX(segment, "+", v-curpsn). 

     END. 
     ELSE DO: /* both > 0, but idxplus is next delim */ 

     v-element = SUBSTRING(segment, v-curPsn, v-idxcolon - v-curPsn). 
     v-curpsn = v-idxcolon + 1. 
     /* No need to recalculate v-idxplus */ 
     v-idxcolon = INDEX(segment, ":", v-curpsn). 

     END. 
    END. 


    /* 
    ** Display result. Skip empty elements. If you want to ignore 
    ** pure white space (e.g. " "), then you can change this to 
    ** IF v-element <> "" 
    */ 
    IF LENGTH(v-element) > 0 THEN DO: 
     MESSAGE v-element 
      VIEW-AS ALERT-BOX INFO BUTTONS OK. 
    END. 
    END. 

    /* 
    ** No more delimiters. But there still might be one element left */ 
    IF v-curpsn < LENGTH(segment) THEN DO: 
    v-element = SUBSTRING(segment, v-curPsn). 
    MESSAGE v-element 
     VIEW-AS ALERT-BOX INFO BUTTONS OK. 
    END. 

END 
関連する問題