• 字符串处理:ABAP中的正则表达式


    正则表达式

    ABAP中可以使用regex的地方

    除了下面两个语句可以使用regex外:

    下面主函数的参数也可以使用regex

    另外,还有两个类也可以使用regex

    正则式语法规则

    下面都是针对单个字符匹配的:

    Special character

    Meaning

    .

    任何单个字符

    C

    .意义一样:可匹配任何单个字符

    d

    任何单个数字字符

    D

    任何单个非数字字符

    l

    任何单个小写字母字符lowercase letter

    L

    任何单个非小写字母字符lowercase letter

    s

    任何一个空白字符a blank character

    S

    任何一个非空白字符a blank character

    u

    任何单个大写字母字符uppercase letter

    U

    任何单个非大写字母字符uppercase letter

    w

    任何单个字母数字字符,包括下划线 _ any alphanumeric character including _

    W

    任何单个非字母数字字符,并排除下划线 _ non-alphanumeric character except for _

    [ ]

    任何单个字符集a value set for single characters

    [^ ]

    字符集之外的其他任何单个字符

    如果^不在[…]里最前面,则^表示只是一个普通的^字符,而不是取反的意思,如[A^B] 中的^ 会匹配普通的字符^

    [ - ]

    范围字符集 a range in a value set for single characters

    如果-不在[…]两个字符之间(但a-z-Z这种不算),则-表示只是一个普通的-字符,而不是范围意思,如[A-Za-z0-9-]中的最后-可以匹配到-

    [[:alnum:]]

    [:alpha:]  [:digit:]并集(字母+数字alphanumeric characters

    [[:alpha:]]

    字母字符集

    [[:blank:]]

    空白字符集 blank characters and horizontal tabulators(制表) in a value set

    [[:cntrl:]]

    控制字符集all control characters in a value set

    [[:digit:]]

     d 等效

    [[:graph:]]

    除开空白字符与垂直制表符外的所有可显示字符

    Description of all characters in a value set that can be displayed apart from blank characters and horizontal tabulators

    [[:lower:]]

    所有小写字母字符集 lowercase letters in a value set

    [[:print:]]

    [:graph:]  [:blank:],可显示字符集,all characters in a value set that can be displayed

    [[:punct:]]

    所有的标点字符集all punctuation characters in a value set

    [[:space:]]

    空白字符+制表符+回车换行符

    blank characters, tabulators, and carriage feeds in a value set

    [[:unicode:]]

    所有大于255Unicode字符

    Unicode characters in a value set with a code larger than 255

    [[:upper:]]

    大写字母字符集

    uppercase letters in a value set

    [[:word:]]

    字母数字+下划线

    alphanumeric characters in a value set, including _

    [[:xdigit:]]

    十六进制数字

    hexadecimal digits in a value set

    a f v

    各种控制字符

    Various platform-specific control characters

    [..]

    为以后增强所保留,目前不支持

    Reserved for later enhancements

    [==]

    为以后增强所保留,目前不支持

    Reserved for later enhancements

     

     

    Special character

    Meaning

    {n}

    出现n

    {n,m}

    出现nm

    {n,m}?

    为以后增强所保留,目前不支持

    Reserved for later enhancements

    {n,m}?, *?,+?属于非贪婪,但目前ABAP中不支持非贪婪

    ?

    0次或1

    *

    0次或多次

    *?

    为以后增强所保留,目前不支持

    Reserved for later enhancements

    +

    1次或多次

    +?

    为以后增强所保留,目前不支持

    Reserved for later enhancements

    |

    或者

    Linking of two alternative expressions

     

    r|st = r|(?:st)不等于(?:r|s)t

    r|s+ = r|(?:s+)不等于(?:r|s)+

    Pattern

    Text

    Match

    H(e|a|u)llo

    Hello

    X

    H(e|a|u)llo

    Hollo

    -

    He|a|ullo

    Hallo

    -

    He|a|ullo

    ullo

    X

    ( )

    捕获组(分组)

    (?: )

    非捕获组(分组,但不捕获)

    1, 2,3...

    正则表达式中的分组引用

    Q ... E

    Q ... E之间的所有字符都会看作是普通的字符:

    Pattern

    Text

    Match

    .+wd

    Special: wd

    -

    .+\w\d

    Special: wd

    X

    .+QwdE

    Special: wd

    X

    Definition of a string of literal characters

    (? ... )

    为以后增强所保留,目前不支持

    Reserved for later enhancements

    (? ... ) 已被保留,除了(?:...)(?=...)(?!...)三种目前支持之外,其他所以的(? ... )这种形式都会抛异常CX_SY_INVALID_REGEX

     

    Special character

    Meaning

    ^

    字符串的开头或行的开头

    Anchor character for the start of a line

    A

    字符串的开头

    Anchor character for the start of a character string

    $

    字符串结尾、字符串结尾的 之前或行的结尾(不会匹配到 ,如果最末有 ,只会匹配到它之前)

    Anchor character for the end of a line

    z

    字符串的结尾

    Anchor character for the end of a character string

    

    字符串的结尾或字符串结尾的 之前

    Like z, whereby line breaks at the end of the character string are ignored

    <

    单词的开头,即匹配单词边界,不匹配任何字符

    Start of a word

    >

    单词的结尾,即匹配单词边界,不匹配任何字符

    End of a word

    

    单词的开头或结尾,即匹配单词边界,不匹配任何字符

    Start or end of a word

    B

    与上面的相反,即非单词边界

    Space between characters within a word

    (?= )

    (?! )

    正向搜索(正)

    Preview condition

    正向搜索(负)

    Negated preview condition

    (?> )

    Cut operator不知道这个有什么用????

     

    Special character

    Meaning

    $0, $&

    整个匹配

    Placeholder for the whole found location

    $1, $2, $3...

    子匹配分组(捕获组)引用

    Placeholder for the register of subgroups

    $`

    匹配到的子串之前的所有字符串

    Placeholder for the text before the found location

    $'

    匹配到的子串之后的所有字符串

    Placeholder for the text after the found location

    (?=…)(?!...)

    注:SAP反向搜索(?<=...)(?<!...)目前不支持,只支持正向搜索(?=...)(?!...),但Java都支持

    DATA text TYPE string.
    DATA result_tab TYPE match_result_tab WITH HEADER LINE.

    text = `Shalalala!`.

    FIND ALL OCCURRENCES OF REGEX '(?:la)(?=!)'
        
    IN text RESULTS result_tab[].

    LOOP AT result_tab .
     
    WRITE: /  result_tab-offset, result_tab-length.
    ENDLOOP.
            7           2

    A z^ $区别

    ^ 指定的匹配必须出现在字符串的开头或行的开头(即  后面第一个字符)。

    $ 指定的匹配必须出现在以下位置:字符串结尾、字符串结尾的 之前或行的结尾(不会匹配到 ,如果最末有 ,只会匹配到它之前)。
    A 指定匹配必须出现在字符串的开头(忽略 Multiline 选项)。 

    z 指定匹配必须出现在字符串的结尾(忽略 Multiline 选项)。
     指定匹配必须出现在字符串的结尾或字符串结尾的 之前(忽略 Multiline 选项)。 

    A z^ $不同的是,只搜索第一行

    DATA text TYPE string.

    "ABAP中如果要在字符中插入回车换行字符时,需要使用 ||,而不是使用单引号引起来
    text = |zzz abc |.
    IF contains( val = text regex = '^abc' ) .
     
    WRITE:/ 'Yes'.
    ELSE.
     
    WRITE:/ 'No'.
    ENDIF.

    "如果是将 ^ 换成 A 时,则结果不会匹配
    IF contains( val = text regex = 'Aabc' ).
     
    WRITE:/ 'Yes'.
    ELSE.
     
    WRITE:/ 'No'.
    ENDIF.
    IF contains( val = text regex = 'z$' ).
     
    WRITE:/ 'Yes'.
    ELSE.
     
    WRITE:/ 'No'.
    ENDIF.
    IF contains( val = text regex = 'c$' ).
     
    WRITE:/ 'Yes'.
    ELSE.
     
    WRITE:/ 'No'.
    ENDIF.
    IF contains( val = text regex = 'zz' ).
     
    WRITE:/ 'Yes'.
    ELSE.
     
    WRITE:/ 'No'.
    ENDIF.
    IF contains( val = text regex = 'z' ).
     
    WRITE:/ 'Yes'.
    ELSE.
     
    WRITE:/ 'No'.
    ENDIF.
    IF contains( val = text regex = 'cz' ).
     
    WRITE:/ 'Yes'.
    ELSE.
     
    WRITE:/ 'No'.
    ENDIF.
    IF contains( val = text regex = 'c' ).
     
    WRITE:/ 'Yes'.
    ELSE.
     
    WRITE:/ 'No'.
    ENDIF.

    Yes

    No

    Yes

    Yes

    No

    No

    No

    Yes

     

    $0…$&$`$′

    替换串里可以出现$&` 

    $0$&:表示的是整个正则式所匹配到的子串,即好比整个正则式使用 ( ) 括起来一样,但不使用 ( ) 括起来整个regex所匹配的子串还是$0,即$0与整个regex是否使用了 ( ) 括起来没有关系,但是,如果使用了( )将整个regex括起来了,则对后面的$1…是有影响的,整个regex此时会是$1,这与Java是不一样的

     

    DATA text TYPE string.

    text = `Yeah!+`.
    REPLACE REGEX `((Y)e(a)h(!))` IN text WITH `-$&-$0-$1-$2-$3-$4-`.
    WRITE:/ text.
    text = `Yeah!`.
    REPLACE REGEX `w+` IN text WITH `-$&-$0-`.
    WRITE:/ text.

    -Yeah!-Yeah!-Yeah!-Y-a-!-+

    -Yeah-Yeah-!

     

    $`表示所匹配到的子串之前的所有字符串,如果多次相同匹配,则所取到的是未经替换过的前面部分源串:

    DATA text TYPE string.
    text = `again and abc and def`.
    REPLACE ALL OCCURRENCES OF REGEX 'and' IN text WITH
    '($0 $`)'.
    WRITE:/ text.

    again (and again ) abc (and again and abc ) def

     

    $'表示所匹配到的子串之后的所有字符串:

     

    DATA: text TYPE string.
    text = `again and again abc`.
    REPLACE ALL OCCURRENCES OF REGEX `again ` IN text WITH
    `($' $0)`.
    WRITE:/ text.

    (and again abc again )and (abc again )abc

    123…

    在分组正则式里,可以使用1, 2, 3…方式引用regex分组,与$分组不一新的是,只要用括号括起来的最左且最外的Regex1,而不是

    Pattern

    Text

    Match

    (["']).+1

    "Hello"

    X

    (["']).+1

    "Hello'

    -

    (["']).+1

    'Hello'

    X

     

     

     

    As of Release 7.00, ABAP supports POSIX-style regular expressions

     

    正则中的特殊字符:. * + ? | ^ $ ( ) [ ] { } 可以使用将这些特殊字符转义普通的字符

    image064[4]

    FIND

    FIND [{FIRST OCCURRENCE}|{ALL OCCURRENCES} OF]

    {[SUBSTRING] sub_string} | {REGEX regex}

      IN [SECTION [OFFSET off] [LENGTH len] OF] dobj

      [IN {BYTE|CHARACTER} MODE]

      [{RESPECTING|IGNORING} CASE]

      [MATCH COUNT  mcnt]

      { {[MATCH OFFSET moff][MATCH LENGTH mlen]}

          | [RESULTS result_tab|result_wa] }

      [SUBMATCHES s1 s2 ...].

     

    0

    至少找到一次

    4

    未找到

     

    [{FIRST OCCURRENCE}|{ALL OCCURRENCES} OF]

    如果未指定或者指定为FIRST OCCURRENCE,则只搜索第一次出现的。

     

    {[SUBSTRING] sub_string} | {REGEX regex}

    FIRST OCCURRENCE或者未指定时,如果sub_string是空String类型的字符串或者内容为空格的固定长度类型(c, d, n, or t)的字符串时,sub_string将会被看作是empty 类型的字符串,并且查找的位置将定位到dobj的首字符前。但如果sub_string是空字符串(包括字符类型字符串类型),使用ALL OCCURRENCES选项,则会抛异常。

    DATA: textTYPE string VALUE`Hey hey`,
          moff TYPEi,
          mlen TYPEi,
          mcnt TYPEi.
    FINDFIRST OCCURRENCE OF  SUBSTRING  ''INtext
         MATCH OFFSET moff
         MATCH LENGTH mlen
         MATCH COUNT  mcnt.
    WRITE: moff, mlen,mcnt.
    FINDFIRST OCCURRENCE OF  SUBSTRING  ' 'INtext
         MATCH OFFSET moff
         MATCH LENGTH mlen
         MATCH COUNT  mcnt.
    WRITE: moff, mlen,mcnt.
    FINDFIRST OCCURRENCE OF  SUBSTRING  ``INtext
         MATCH OFFSET moff
         MATCH LENGTH mlen
         MATCH COUNT  mcnt.
    WRITE: moff, mlen,mcnt.
    FINDFIRST OCCURRENCE OF  SUBSTRING  ` `INtext
         MATCH OFFSET moff
         MATCH LENGTH mlen
         MATCH COUNT  mcnt.
    WRITE: moff, mlen,mcnt.
    "
    以下三个语句运行时会抛异常

    "FIND ALL OCCURRENCES OF SUBSTRING  `` IN text MATCH OFFSET moff.
    "FIND ALL OCCURRENCES OF SUBSTRING  '' IN text MATCH OFFSET moff.
    "FIND ALL OCCURRENCES OF SUBSTRING  ' ' IN text MATCH OFFSET moff.

               0           0           1           0           0           1           0           0           1           3           1         1

     

    sub_string为固定长度类型的字符串时,尾部空格将被忽略,如果不想忽略尾部空格,则使用String类型的sub_string

     

    regex不允许为空的String类型的字符串或者内容只有空格的固定长度类型(c, d, n, or t)的字符串,以下编译时会出错:

    DATA: textTYPE string VALUE`Hey hey`,
          moff TYPEi.
    FINDFIRST OCCURRENCE OF  REGEX  ''INtext
         MATCH OFFSET moff.
    FINDFIRST OCCURRENCE OF  REGEX  ``INtext
         MATCH OFFSET moff.

     

     

    IN [SECTION [OFFSET off] [LENGTH len] OF] dobj

    如果未加上SECTION选项,将对整个dobj字符串进行匹配操作。如果指定了SECTION选项,则OFFSETLENGTH必须选择一个。如果指定如果指定了OFFSET但未指定LENGTH查找的区域从OFFSETdobj的最后;如果指定了LENGTH但未指定OFFSETOFFSET将隐含为0OFFSETLENGTH需要大于或等于0,通过OFFSETLENGTH定位到的子字符串段必须要位于dobj里。

     

    [{RESPECTING|IGNORING} CASE]

    是否区分大小写,默认区分

     

    [MATCH COUNT  mcnt]

    成功查找的次数,如果使用了FIRST OCCURRENCE选项,则通常是1

     

    [MATCH OFFSET moff]

    最后一次匹配的子串(是指整体正则分组,即Java中的第0组)起始位置。如果没有查找到,则为以前的值。

    注:FIND不影响sy-fdpos系统字段

     

    [MATCH LENGTH mlen]

    最后一次匹配到的子串(是指整体正则分组,即Java中的第0组)的长度(注:与REPLACE不同的是,REPLACE指的是替换的长度)。

     

    [RESULTS result_tab|result_wa]

    result_tab接收所有匹配结果,而result_wa只能接收最后一次匹配结果

    FIRST OCCURRENCE 一般与result_wa 一起使用,如果与result_tab结合,则最多只有一条结果。

     

    如果查找不成功,则result_tabinitialresult_wa为以前的值。

     

    result_wa适合于与FIRST OCCURRENCE结合使用,而result_tab适合于与ALL OCCURRENCES结合使用。

     

    result_tab必须是MATCH_RESULT_TAB类型的内表

    result_waMATCH_RESULT类型的结构

    image065[4]

    • OFFSET 匹配到的子字符串位置dobj的位置
    • LENGTH 匹配到的子字符串长度
    • SUBMATCHES 类型为SUBMATCH_RESULT_TAB 的内表,行类型为SUBMATCH_RESULT。该类型存储了所有子分组匹配(只要是括号括起来的,就是一个子分组,那怕括起来的是整个正则式——如果整个正则式不括起来,则不会像Java那样自动成为一个子分组
    • LINE 仅在使用FIND IN TABLE才有意思

    image066[4]

     

    [SUBMATCHES s1 s2 ...]

    SUBMATCHES 选项只在REGEX regex情况下使用,并且只会接收使用括号进行分组的子组。

    如果变量s1 s2 ...比分组的数量多,则多余的变量被initial;如果变量s1 s2 ...比分组的数量少,则多余的分组将被忽略

     

    DATA: text TYPE string,
          moff
    TYPE i,
          mlen
    TYPE i,

    mcnt TYPE i,
          s1  
    TYPE string,

          s2  
    TYPE string,
          s3  
    TYPE string,
          s4  
    TYPE string.
    text = `Hey hey, my my, Rock Hey hey, my my,`.
    FIND ALL OCCURRENCES OF REGEX `(w+)W+1W+(w+)W+2`
        
    IN text
         IGNORING
    CASE

    "以下两个变量存储的是第二次匹配到的子串(整体正则式)相关信息
         MATCH OFFSET moff
         MATCH LENGTH mlen

    "会发生2次匹配

    MATCH COUNT  mcnt
         "
    会发生两次匹配,第一次为:Hey hey, my my,第二次为:Hey hey, my my

         "注,虽然这里使用使用了4个变量接收分组,但正则式中每次只会有两个

         "分组,所以接收每次匹配结果只需要2个变量,s3s4不会用到,而不是第二次

         "时将匹配到的结果存放到s3s4
         SUBMATCHES s1 s2 s3 s4
    .
    WRITE: / moff, / mlen,/ s1, / s2, / s3,/ s4.

            21

            14

             2

    Hey

    my

     

    精确查找(一次性解析)

    {[SUBSTRING] sub_string} | {REGEX regex}:为FIND的两种使用方式。第一种表式在dobj串中精确查找子字符串sub_stringSUBSTRING可以省略),此种方式sub_string不支持正则试,即使使用也会当作普通字符串。如:

      DATA: result_tab TYPE match_result_tab.
     
    FIELD-SYMBOLS <match> LIKE LINE OF
    result_tab.
     
    FIND ALL OCCURRENCES OF `now` IN`Everybody knows this is nowhere`

          
    RESULTS result_tab.
     
    LOOP AT result_tab ASSIGNING
    <match>.
       
    WRITE
    : / <match>-offset, <match>-length.
     
    ENDLOOP
    .

            11           3

            24           3

    精确查找(循环查找)

    上面程序可以使用以下循环方式来代替(这种方式适合以7.0以前版本),而不是将结果一次性存入到match_result_tab类型的内表中:

      DATA: off  TYPE i,
            moff
    TYPE i
    ,
            mlen
    TYPE i
    .
      off =
    0
    .
     
    WHILE sy-subrc = 0
    .
       
    FIND `now` IN SECTION OFFSET off OF

            
    `Everybody knows this is nowhere`
           
     MATCH OFFSET moff
            
    MATCH LENGTH
    mlen.
       
    IF sy-subrc = 0
    .
         
    WRITE
    : / moff,mlen.
          off = moff + mlen.
       
    ENDIF
    .
     
    ENDWHILE
    .

            11           3

            24           3

    使用正则式

    DATA: moff TYPE i,
          mlen
    TYPE i,
          s1
    TYPE string,
          s2
    TYPE string,
          s3
    TYPE string,
          s4
    TYPE string.
    "(a).|([ab]+)等效于 ((a).)|([ab]+)。正则式是按最贪婪(最多或者最长匹配)
    "
    方式来匹配,所以 (a).|([ab]+) 会选择后者。另外,分组数只与括号有关,并
    "
    按括号从左到右,从外到里顺次为第一组,第二组,第...,与 | 没有关系,即分
    "
    组数不会随着 | 的正则式选择不同而改变
    FIND REGEX
     '(((a).)|([ab]+))' IN 'oooababboo'
        
    MATCH OFFSET moff
        
    MATCH LENGTH
    mlen
        
    SUBMATCHES s1 s2 s3 s4.

    WRITE: / 's1=',s1,'s2=',s2,'s3=',s3,'s4=',s4, / moff,mlen.

    s1= ababb s2=  s3=  s4= ababb

             3           5

     

     

    DATA: result_tab TYPE match_result_tab.
    FIND ALL OCCURRENCES OF REGEX `((ab)|(ba))`
    IN 'abba'
         RESULTS result_tab
    .

    image067[4]

    image068[4]

    image069[4]

    因为正则表达式中的子分组使用或连接的,每次匹配过程中,虽然有3个子分组,但每次只有其中某两个才能真正匹配上。

     

    匹配部分分组(SUBMATCHES )

      DATA: moff TYPE i,
            mlen
    TYPE i
    ,
            s1  
    TYPE
    string,
            s2  
    TYPE
    string.
     
    FIND REGEX `((w+)W+2W+(w+)W+3)`

          
    IN `Hey hey, my my, Rock and roll can never die`
           IGNORING
    CASE
           MATCH OFFSET moff
           MATCH LENGTH mlen
          
    SUBMATCHES s1 s2."根据从外到内,从左到右的括号顺序依次存储到s1 s2…中,注:取出部分一定要使用括号括起来,即使是取出匹配整个正则式的部分也得括起来,这与Java不同,正则式外层默认情况下是没有括号括起来,但Java默认情况下整体就是一个分组,且是第0分组,但ABAP是从1开始编号子分组的(指使用括号括起来的才算,如果整个正则式未使用括号,则不会算做一个子分组)
      WRITE: /  s1, / s2,/ moff ,/ mlen.

    Hey hey, my my

    Hey

             0

            14

    匹配所有分组(RESULTS result_tab)公共函数

    image070[4]

    START-OF-SELECTION.
     
    DATA: result TYPE STANDARD TABLE OF string WITH HEADER LINE
    .
     
    "
    Java不同,只要是括号括起来的都称为子匹配(即整体也得用括号括起来了),不管括号嵌套多少层,统
     
    "称为子匹配,且匹配到的所有子串都会存储到MATCH_RESULT-SUBMATCHES中,
     
    "即使最外层的括号匹配子串也会存储到SUBMATCHES内表中。括号解析的顺序为:
     
    "从外到内,从左到右的优先级顺序来解析匹配结构。Java中的group(0)存储的
     
    "是整体匹配串,即使整体未(或使用)使用括号括起来
     
    PERFORM get_match TABLES result
             
    USING '20110921' '^(((d{2})(d{2}))(d{2})(d{2}))$'
    .
     
    LOOP AT
    result .
       
    WRITE
    : / result.
     
    ENDLOOP
    .

    FORM get_match  TABLES p_result"
    默认会带表头
                   
    USING    p_str
                             p_reg.
     
    DATA: result_tab TYPE match_result_tab WITH HEADER LINE
    .
     
    DATA: subresult_tab TYPE submatch_result_tab WITH HEADER LINE
    .

      "
    注意:带表头时 result_tab 后面一定要带上中括号,否则激活时出现奇怪的问题
     
    FIND ALL OCCURRENCES OF REGEX p_reg IN p_str RESULTS result_tab[].
     
    LOOP AT
    result_tab .
        p_result = p_str+
    result_tab-offset(result_tab-length).
       
    APPEND p_result.
        subresult_tab[] = result_tab-submatches.
       
    LOOP AT
    subresult_tab.
          p_result = p_str+subresult_tab-offset(subresult_tab-length).
         
    APPEND
    p_result.
       
    ENDLOOP
    .
     
    ENDLOOP
    .
    ENDFORM
    .

    20110921

    20110921

    2011

    20

    11

    09

    21

    REPLACE

    REPLACE [{FIRST OCCURRENCE}|{ALL OCCURRENCES} OF]

    {[SUBSTRING] sub_string} | {REGEX regex}
            IN [SECTION [OFFSET off] [LENGTH len] OF] dobj

    WITH new
            [IN {BYTE|CHARACTER} MODE]
            [{RESPECTING|IGNORING} CASE]
            [REPLACEMENT COUNT rcnt]
            { {[REPLACEMENT OFFSET roff]
               [REPLACEMENT LENGTH rlen]}
            | [RESULTS result_tab|result_wa] }.

    语法与FIND相似。

     

    如果new尾部空格需要保留,则要使用String类型的new,其他固定长度类型的new字符,会忽略掉尾部空格。

     

    {FIRST OCCURRENCE}|{ALL OCCURRENCES} OF

    FIRST OCCURRENCE或者未指定时,只替换第一次匹配的;ALL OCCURRENCES则替换所有子匹配串

     

    {[SUBSTRING] sub_string} | {REGEX regex}

    [SUBSTRING] sub_string:以固定的字符串为匹配模式进行搜索并替换,与前面替换指定的字符串REPLACE是一样的。

     

    FIRST OCCURRENCE或者未指定时,如果sub_string是空String类型的字符串或者内容为空格的固定长度类型(c, d, n, or t)的字符串时,sub_string将会被看作是empty 类型的字符串,并且查找替换的位置将定位到dobj的首字符前,并且将new插入到dobj最前面。但如果sub_string是空字符串(包括字符类型字符串类型),使用ALL OCCURRENCES选项,则会抛异常。

     

    sub_string为固定长度类型的字符串时,尾部空格将被忽略(这与老式的REPLACE规则不同),如果不想忽略尾部空格,则使用String类型的sub_string

     

    REGEX regex:使用正则表达式进行匹配替换。

    regex不允许为String类型的字符串或者内容只有空格的固定长度类型(c, d, n, or t)的字符串。

     

    DATA text TYPE string VALUE '-uu-'.
    "U*表示0个或多个U,当为0个时,字符间的空隙就相匹配"U*UU相匹配,替换的结果为第三个 x
    REPLACE ALL OCCURRENCES OF REGEX 'u*' IN text WITH 'x'.

    WRITE:/ text.

    x-xx-x

     

    IN [SECTION [OFFSET off] [LENGTH len] OF] dobj

    如果未加上SECTION选项,将对整个dobj字符串进行匹配替换操作。如果指定了SECTION选项,则OFFSETLENGTH必须选择一个。如果指定如果指定了OFFSET但未指定LENGTH替换的区域从OFFSETdobj的最后;如果指定了LENGTH但未指定OFFSETOFFSET将隐含为0OFFSETLENGTH需要大于或等于0,通过OFFSETLENGTH定位到的子字符串段必须要位于dobj里。该选项与前替换某个区间上的字符串REPLACE是一样的,与FIND也相同。

     

    [{RESPECTING|IGNORING} CASE]

    区分与忽略大小写,对在 IN CHARACTER MODE 模式下使用,默认区别大小写

     

    [REPLACEMENT COUNT rcnt]

    成功替换的次数,如果没有发生替换,则为0

    注:如果dobj为固定长度类型的字符串时,则发生替换的次数 rcnt 可能少于本应该查找到的次数。

     

    [REPLACEMENT OFFSET roff]

    最后一次替换发生在 dobj 中的起始位置,如果没有发生替换,则保留的是以前的值。

     

    [REPLACEMENT LENGTH rlen]

    最的一次dobj替换完成后替换结果段的长度(注:不是指查到的sub_string长度的,而是指定成功替换后被插入部分的长度,这与FIND函数是不一样的,这里一般等于 new 的长度),如果没有发生替换,则保留的是以前的值。

    注:如果dobj为固定长度类型的字符串时,rlen可能小于 new 的长度。

     

    关于rcnt变少、rlen变小的示例:

    DATA: text(9) VALUE 'aaacccccc'.
    DATA: roff TYPE i, rlen  TYPE i,rcnt  TYPE i.

    REPLACE ALL OCCURRENCES OF 'ccc' IN text WITH 'ddd'
            REPLACEMENT
    COUNT rcnt
            REPLACEMENT OFFSET roff
            REPLACEMENT LENGTH rlen
    .


    "ddd:     2 6 3 替换值 new 未被截断且后面还有未进行替换处理的字符串(ccc),继续查找与替换
    "dddd:    2 7 2 替换值 new 未被截断且后面还有未进行替换处理的字符串(cc),继续查找与替换
    "ddddd:   2 8 1
    替换值 new 未被截断且后面还有未进行替换处理的字符串(c),继续查找与替换
    "dddddd:  1 3 6 替换值 new 未被截断但后面不再有其他字符串,所以不再查找与替换(替换次数1小于本应该查找到的次数2,因为在经过第1次替换后,被替代后面的所有字符串都会被截断,下面也是一样道理)
    "ddddddd: 1 3 6
    替换值 new 被截断,所以不再查找与替换
    WRITE
    : / rcnt, / roff, / rlen.

     

    [RESULTS result_tab|result_wa]

    如果发生了替换操作,则替换的起始位置、匹配到的字符串长度都会存储到一个行结构为result_waresult_tab内表中,与FIND中的RESULTS result_tab选项意思相当,只是result_tab and result_wa的类型为REPL_RESULT_TAB or REPL_RESULT,并且REPL_RESULT里没有内嵌SUBMATCHES

    image071[4]

     

    替换指定位置

      DATA: text1 TYPE string,
            text2
    TYPE c LENGTH 18
    ,
            off
    TYPE i
    ,
            len
    TYPE i
    .
      text1 = text2 =
    'I know you know'
    .
     
    "
    先查找位置:查找第一次匹配位置
     
    FIND 'know' IN text1 MATCH OFFSET off
                           MATCH LENGTH len.
     
    "
    再根据指定位置替换
     
    REPLACE SECTION OFFSET off LENGTH len OF:
                      text1
    WITH 'should know that'
    ,
                      text2
    WITH 'should know that'
    .
     
    "text2
    替换后被截断
     
    WRITE: / text1,/ text2 , sy-subrc.

    I should know that you know

    I should know that     2

     

    DATA: text1 TYPE string,
         
    cnt TYPE i
    ,
          off
    TYPE i
    ,
          len
    TYPE i
    .
    text1 =
    'I know you know'
    .
    REPLACE ALL OCCURRENCES OF 'know' IN

           
    SECTION OFFSET 11 LENGTH 4 of"11~14索引范围内匹配替换
            text1
    WITH 'should know that'
                  REPLACEMENT
    COUNT  cnt"发生的替换次数
                  REPLACEMENT OFFSET off
    "最后一次发生替换的位置
                  REPLACEMENT LENGTH len.
    WRITE: / text1, cnt, off,len.

    I know you should know that          1          11          16

    使用正则式

    DATA text TYPE string VALUE '-uu-'.

    "字符间隙也会被看作是一个字符串元素,依照正则式,字符串首间隙、第二字符间隙被看作是满足正则式的,另外第三与第四字符间隙和两个 u 字符一起满足正则式(贪婪)
    REPLACE ALL OCCURRENCES OF REGEX 'u*' IN text WITH 'x'
    .
    WRITE: text
    .

    x-xx-x

     

     

    DATA: text1 TYPE string,
          text2(
    18) TYPE c
    ,
         
    cnt TYPE i
    ,
          off
    TYPE i
    ,
          len
    TYPE i
    .
    text1 = text2 =
    'I know you know'
    .
    REPLACE ALL OCCURRENCES OF 'know' IN
    :
            text1
    WITH 'should know that'

                  REPLACEMENT
    COUNT  cnt"发生的替换次数
                  REPLACEMENT OFFSET off
    "最后一次发生替换的位置
                  REPLACEMENT LENGTH len.
    WRITE: / text1, cnt
    , off,len.
    "
    由于第一次替换后超出了 text2 本身的长度,所以不会再发生第二次替换
    REPLACE ALL OCCURRENCES OF 'know' IN:
            text2
    WITH 'should know that'

                  REPLACEMENT
    COUNT  cnt
                  REPLACEMENT OFFSET off
                  REPLACEMENT LENGTH len.
    WRITE: / text2, cnt, off,len.

    I should know that you should know that          2          23          16

    I should know that                                   1           2          16

    正则类

    ABAP提供了两个类来支持正则式:

    Regex class cl_abap_regexJava中的 java.util.regex.Pattern的类对应

    Matcher class cl_abap_matcherJava中的 java.util.regex.Matcher的类对应

    image072[4]

     

    image073[4]

     

    是否包含(也可在正则式中使用 ^  $ 用于完全匹配检查,或者使用 ^ 检查是否匹配开头,或者使用 $ 匹配结尾),下面的TABLE参数表示需要在TABLE中进行索引,与TEXT是一样都是搜索源,如果TEXTTABLE同时都指定时,会忽略TABLE

    image074[4]

     

     CONTAINS  MATCHES 方法配合使用:

    DATA: matcher TYPE REF TO cl_abap_matcher,
          match TYPE match_result.
    IF cl_abap_matcher=>matches( pattern = 'dbai.*' text = 'dbaiabd' ) = abap_true.
      matcher = cl_abap_matcher=>get_object( ).
      match = matcher->get_match( ).
    WRITE / matcher->text+match-offset(match-length).
    ENDIF
    .

    image075[4]

     

    是否完全匹配(正则式中不必使用 ^  $

    image076[4]

     

     

    DATA: matcher TYPE REF TO cl_abap_matcher,
          match
    TYPE
    match_result,
          itab
    TYPE
    match_result_tab,
         
    line LIKE LINE OF
    itab.
    matcher = cl_abap_matcher=>create( pattern =
    '<[^<>]*>' text = '<html>hello</html>'
    ).
    itab = matcher->
    find_all
    ( ).
    LOOP AT itab INTO line
    .
     
    WRITE: / matcher->text,line-offset,line-length,matcher->text+line-offset(line
    -length).
    ENDLOOP
    .

    image077[4]

    image078[4]

     

    INDEX为子匹配项(使用括号括起来的正则式)索引,默认为0,表示整体匹配正则式:

    image079[4]

     

    image080[4]

     

    image081[4]

    image082[4]

    image083[4]

     

    image084[4]

    image085[4]

    image086[4]

    image087[4]

     

    创建正则对象

    DATA: regex TYPE REF TO cl_abap_regex,
          matcher
    TYPE REF TO
    cl_abap_matcher.

     

    l  直接Create

    CREATE OBJECT regex EXPORTING pattern = 'a*b' ignore_case = abap_true.
    CREATE OBJECT matcher EXPORTING regex = regex text = 'text'
    .

    image088[4]

     

    下面TEXT表示当前正被搜索的搜索源字符串,TABLE也是搜索源。如果TEXTTABLE同时都指定时,会忽略TABLE

    image089[4]

     

    l  使用静态工厂方法

    matcher = cl_abap_matcher=>create( pattern = 'a*b' text = 'text' ).

    image090[4]

  • 相关阅读:
    bzoj1593[Usaco2008 Feb]Hotel旅馆
    spoj1182 Sorted bit squence/[USACO2003 Dec]Cow Queueing
    [USACO2003 Dec]Cow Queueing数数的梦 (基础水数位DP带注释!)
    后缀数组模版+注释
    bzoj1690/poj3621[Usaco2007 Dec]奶牛的旅行
    bzoj1731/poj3169[Usaco2005 dec]Layout 排队布局
    bzoj2467[中山市选2010]生成树
    bzoj1594[Usaco2008 Jan]Haybale Guessing猜数游戏
    poj 1035 -- Spell checker
    poj 1611 -- The Suspects
  • 原文地址:https://www.cnblogs.com/jiangzhengjun/p/4292994.html
Copyright © 2020-2023  润新知