我有一个字符串
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 :(得分: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.
答案 1 :(得分: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.
答案 2 :(得分:0)
如果您只有两个分隔符,则此代码是一种干净的搜索方式。它可以扩展为三个或更多分隔符,但我可能会以不同的方式构造代码。 (我会遍历一个分隔符列表。如果你需要这样的代码,请告诉我。)
此代码的一个目的是最小化执行的字符串搜索的数量。不是在每次查找后搜索两个分隔符,而是只搜索一个分隔符。我相信这会使它在不失透明度的情况下保持高效 - 但我没有做基准测试,我可能错了。与往常一样,最佳解决方案将取决于数据的性质。
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