ABAP正则表达式 特殊字符处理

    REPLACE ALL OCCURRENCES OF REGEX '[[:space:]]' IN <fs_purhdinfo>-cell_value  WITH ''."可去掉空格或回车键
    REPLACE ALL OCCURRENCES OF  ':' IN <fs_purhdinfo>-cell_value WITH ''."可去掉空格或回车键
    REPLACE ALL OCCURRENCES OF  REGEX '[[:cntrl:]]' IN <fs_purhdinfo>-cell_value WITH ''.

    REPLACE ALL OCCURRENCES OF REGEX '[[:space:]]' IN <fs_purhdinfo>-cell_formula  WITH ''."可去掉空格或回车键
    REPLACE ALL OCCURRENCES OF  ':' IN <fs_purhdinfo>-cell_formula WITH ''."可去掉空格或回车键
    REPLACE ALL OCCURRENCES OF  REGEX '[[:cntrl:]]' IN <fs_purhdinfo>-cell_formula WITH ''.

正则表达式:

是否包含字母数字类,比如域账号判断

IF cl_abap_matcher=>matchespattern '^[a-z0-9A-Z_]+$'   text lv_ key ).

IF cl_abap_matcher=>matchespattern '[a-z|A-Z]*-?[a-z|A-Z]*[0-9?]*' text lv_key ).

判断字符串中是否包含汉字
*"     REFERENCE(IV_INPUT) TYPE  STRING
*"     REFERENCE(EV_OUT) TYPE  C
  DATAalpha_num(120TYPE c.
  alpha_num ' abcdefghijklopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,./;''[]\-=`<>?:"{}|_+~!@#$%^&*()'.

  IF NOT IV_input CO alpha_num.
    EV_OUT ABAP_TRUE"'含有汉字'.
  ELSE.
    EV_OUT SPACE.     "不含汉字
  ENDIF.
ENDFUNCTION.

特殊字符:

  REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>horizontal_tab IN ls_z023-kxytx WITH space.  "TAB
  REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf IN ls_z023-kxytx WITH space.           "回车换行
  REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>newline IN ls_z023-kxytx WITH space.         "换行
  CONDENSE ls_z023-kxytx NO-GAPS.

正则表达式

ABAP中可以使用regex的地方

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

  • FIND
  • REPLACE

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

  • count()
  • contains()
  • find()
  • match()
  • matches()
  • replace()
  • substring()

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

  • CL_ABAP_REGEX
  • CL_ABAP_MATCHER

正则式语法规则

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

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:]]

所有大于255的Unicode字符

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 \n \r \t \v

各种控制字符

Various platform-specific control characters

[..]

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

Reserved for later enhancements

[==]

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

Reserved for later enhancements

Special character

Meaning

{n}

出现n次

{n,m}

出现n到m次

{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

.+\w\d

Special: \w\d

-

.+\\w\\d

Special: \w\d

X

.+\Q\w\d\E

Special: \w\d

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

$

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

Anchor character for the end of a line

\z

字符串的结尾

Anchor character for the end of a character string

\Z

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

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

\<

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

Start of a word

\>

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

End of a word

\b

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

Start or end of a word

\B

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

Space between characters within a word

(?= )

(?! )

正向搜索(正)

Preview condition

正向搜索(负)

Negated preview condition

(?> )

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

Special character

Meaning

0, 0,&

整个匹配

Placeholder for the whole found location

1, 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、\Z与^ 、$区别

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

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

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

\A 、\z、\Z与^ 、$不同的是,只搜索第一行
 

DATA text TYPE string.

"在ABAP中如果要在字符中插入回车换行字符时,需要使用 ||,而不是使用单引号引起来
text = |zzz\nabc\n|.
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 = 'z\z' ).
  WRITE:/ 'Yes'.
ELSE.
  WRITE:/ 'No'.
ENDIF.
IF contains( val = text regex = 'z\Z' ).
  WRITE:/ 'Yes'.
ELSE.
  WRITE:/ 'No'.
ENDIF.
IF contains( val = text regex = 'c\z' ).
  WRITE:/ 'Yes'.
ELSE.
  WRITE:/ 'No'.
ENDIF.
IF contains( val = text regex = 'c\Z' ).
  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− 1−2- 3− 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

\1、\2、\3…

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

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类型的字符串或者内容为空格的固定长度类型(cdn, 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类型的字符串或者内容只有空格的固定长度类型(cdn, 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选项,则OFFSET与LENGTH必须选择一个。如果指定如果指定了OFFSET,但未指定LENGTH时,查找的区域从OFFSET到dobj的最后;如果指定了LENGTH,但未指定OFFSET时,OFFSET将隐含为0。OFFSETLENGTH需要大于或等于0,通过OFFSET与LENGTH定位到的子字符串段必须要位于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_tab为initial,result_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+\1\W+(\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个变量,s3与s4不会用到,而不是第二次

     "时将匹配到的结果存放到s3与s4中
     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+\2\W+(\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类型的字符串或者内容为空格的固定长度类型(cdn, or t)的字符串时,sub_string将会被看作是empty 类型的字符串,并且查找替换的位置将定位到dobj的首字符前,并且将new插入到dobj最前面。但如果sub_string是空字符串(包括字符类型字符串类型),使用ALL OCCURRENCES选项,则会抛异常。

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

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

regex不允许为空String类型的字符串或者内容只有空格的固定长度类型(cdn, 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选项,则OFFSET与LENGTH必须选择一个。如果指定如果指定了OFFSET,但未指定LENGTH时,替换的区域从OFFSET到dobj的最后;如果指定了LENGTH,但未指定OFFSET时,OFFSET将隐含为0。OFFSETLENGTH需要大于或等于0,通过OFFSET与LENGTH定位到的子字符串段必须要位于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_wa的result_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_regex与Java中的 java.util.regex.Pattern的类对应

Matcher class cl_abap_matcher与Java中的 java.util.regex.Matcher的类对应

image072[4]

 

image073[4]

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

image089[4]

l  使用静态工厂方法

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

image090[4]

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1524105.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

AI绘画SD中如何安装/更新/卸载 Stable Diffusion WebUI 插件?SD新手必看的保姆级教程!

大家好&#xff0c;我是画画的小强 最近有一部分朋友对如何在AI绘画StableDiffusion中 安装管理 WebUI 插件十分陌生&#xff0c;不知道如何下手。 今天就系统地为大家介绍一下 WebUI 插件安装、更新、卸载的相关知识&#xff0c;让初学者能快速掌握插件的使用方法&#xff0c…

iomuxc、pinctrl子系统、gpio子系统(学习总结)

iomuxc、pinctrl子系统、gpio子系统三者的关系 相互依赖&#xff1a;IOMUXC、pinctrl子系统和gpio子系统在功能上相互依赖。IOMUXC提供了引脚复用和电气属性的配置能力&#xff0c;pinctrl子系统负责从设备树中获取这些配置信息并完成初始化&#xff0c;而gpio子系统则在引脚被…

C++中protobuffer的具体使用方法以及重要原理的实现

一、protobuffer的具体使用 对于基本的知识可以看我之前的文章。 那一片文章主要是知识点&#xff0c;这一片是实战。 1、头部 我们通过syntax 这个来指定版本号&#xff0c;如果不写的话就会默认为proto2&#xff0c;2这个版本是一个比较旧的版本。旧的版本写起来就比较繁琐。…

25届计算机毕业设计,如何打造Java SpringBoot+Vue博客系统,一步一脚印,开发心得分享

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

Spring源码-从源码层面讲解声明式事务配置文件的加载和相关对象的创建1(创建对向,属性填充,动态代理均有涉及)

tx.xml事务配置文件的解析 <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema/beans"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xmlns:context"http://www.spr…

项目实战 - 贪吃蛇

目录 1. 基本功能 2. 技术要点 3. 环境 4. 效果演示 5. 控制台设置 6. Win32 API介绍 6.1 Win32 API 6.2 程序台控制(Console) 6.3 控制台屏幕上的坐标(COORD) 6.4 GetStdHandle 6.5 GetConsoleCursorInfo 6.5.1 CONSOLE_CURSOR_INFO 6.6 SetConsoleCursorInfo 6…

Android终端如何快速接入GB28181平台实现实时音视频回传

技术背景 GB28181是由中国国家标准委员会发布的基于IP网络的安防视频监控标准。Android平台GB28181设备对接模块&#xff0c;主要涉及到视频监控领域&#xff0c;可实现不具备国标音视频能力的 Android终端&#xff0c;通过平台注册接入到现有的GB/T28181—2016服务&#xff0…

数据结构——单链表查询、逆序、排序

1、思维导图 2、查、改、删算法 //快慢排序法找中间值 int mid_link(Link_t *plink) {Link_Node_t *pfast plink->phead;Link_Node_t *pslow pfast;int m 0;while(pfast ! NULL){pfast pfast->pnext;m;if(m % 2 0){pslow pslow->pnext;}}printf("%d\n&quo…

WPF-快速构建统计表、图表并认识相关框架

一、使用ScottPlot.Wpf 官网地址&#xff1a;https://scottplot.net/quickstart/wpf/ 1、添加NuGet包&#xff1a;ScottPlot.Wpf 2、XAML映射命名空间&#xff1a; xmlns:ScottPlot"clr-namespace:ScottPlot.WPF;assemblyScottPlot.WPF" 3、简单示例&#xff1a;…

刘润《关键跃升》读书笔记6

把教练传授内容的知识含量分成五个级别&#xff1a;⽩⽔级、啤酒级、⻩酒 级、红酒级和⽩酒级&#xff08;⻅图3-4&#xff09; 第⼀个层级是⽩⽔级&#xff08;0&#xff09;。教练在传授的时候&#xff0c;什么都没有教&#xff0c;只 会训⼈。 ⼆个层级是啤酒级&#xff08…

LaTeX各符号表示方式(持续更新~)

- "\mu"&#xff1a;穆 miu - "\sigma"&#xff1a;西格玛xigema - "\lambda"&#xff1a;兰姆达或拉姆达lamuda - "\alpha"&#xff1a;阿尔法aerfa - "\beta"&#xff1a;贝塔beita - "\gamma"&#xff1a;伽马…

比特币客户端和API

1. 比特比客户端的安装 Bitcoin Core 客户端适用于从 x86 Windows 到 ARM Linux 的不同架构和平台&#xff0c;如下图所示&#xff1a; 2. Bitcoin Core客户端的类型 2.1 Bitcoind Bitcoind 末尾的字母 d 表示 daemon (守护程序&#xff09;。所谓守护程序&#xff0c;就是指…

deep-live-cam实时换中文整合包下载,双击exe直接运行

windows环境整合包下载地址&#xff1a; 点击下载 直接解压&#xff0c;双击启动.exe即可使用 硬件要求&#xff1a;有英伟达显卡&#xff0c;且要支持CUDA 硬件不符合要求也不用急&#xff0c;软件也有对应mac版本和windows非N卡版本&#xff0c;我还没做成整合包&#xff0c;…

【python因果推断库6】使用 pymc 模型的工具变量建模 (IV)1

目录 使用 pymc 模型的工具变量建模 (IV) 使用 pymc 模型的工具变量建模 (IV) 这份笔记展示了一个使用工具变量模型&#xff08;Instrumental Variable, IV&#xff09;的例子。我们将会遵循 Acemoglu, Johnson 和 Robinson (2001) 的一个案例研究&#xff0c;该研究尝试解开…

大屏可视化:阿里 DataV 大屏怎么做自适应的?

你好&#xff0c;我是沐爸&#xff0c;欢迎点赞、收藏、评论和关注。 阿里 DataV 大屏是一款功能强大的数据可视化应用搭建工具&#xff0c;由阿里云提供&#xff0c;旨在帮助用户通过图形化的界面轻松搭建专业水准的可视化应用。 下面我们一起看下 DataV 大屏 是如何做自适应…

Leetcode 第 408 场周赛题解

Leetcode 第 408 场周赛题解 Leetcode 第 408 场周赛题解题目1&#xff1a;3232. 判断是否可以赢得数字游戏思路代码复杂度分析 题目2&#xff1a;3233. 统计不是特殊数字的数字数量思路代码复杂度分析 题目3&#xff1a;3234. 统计 1 显著的字符串的数量思路代码复杂度分析 题…

矮草坪渲染尝试

本来说写unity里的&#xff0c;由于three测试方便&#xff0c;先试试three 这个图片是目标效果 可以看见草很矮&#xff0c;很密集&#xff0c;如果用instance来绘制的话&#xff0c;遭不住的 忽然发现这个效果很像绒毛效果 于是找了博客康康 https://zhuanlan.zhihu.com/p/256…

Ubuntu | 安装 Truffle 框架(安装缓慢)

目录 预备工作具体步骤Step1&#xff1a;安装 nvma. 官方方式&#xff08;可能失败&#xff09;b. 压缩包安装方式 Step2&#xff1a;安装 node.js 和 npmStep3&#xff1a;安装 Truffle 参考博客 前言&#xff1a;昨天安装 Truffle 框架&#xff0c;结果缓冲条转了一晚上都没安…

企业全球组网有哪几种常用的组网方式?

为了实现全球范围内的高效通信和数据传输&#xff0c;企业需要选择适合自身需求的组网方式。企业全球组网的有哪几种主要方式&#xff1f;一般包括传统的MPLS网络、云网络、SD-WAN技术和全球VPN&#xff0c;以帮助企业在全球范围内建立稳定、高效的网络连接。 1、传统的MPLS网络…

探索AWS EC2:云计算的强大引擎

在数字化转型的浪潮中&#xff0c;企业对计算资源的需求不断增长。亚马逊弹性计算云&#xff08;EC2&#xff09;作为AWS&#xff08;亚马逊网络服务&#xff09;的核心产品之一&#xff0c;凭借其强大的功能和灵活性&#xff0c;成为了全球企业构建和扩展应用的首选平台。无论…