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=>matches( pattern = '^[a-z0-9A-Z_]+$' text = lv_ key ).

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

判断字符串中是否包含汉字
*" REFERENCE(IV_INPUT) TYPE STRING
*" REFERENCE(EV_OUT) TYPE C

DATA: alpha_num(120) TYPE 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

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

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选项,则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类型的结构

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

[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.

因为正则表达式中的子分组使用或连接的,每次匹配过程中,虽然有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)公共函数

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选项,则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:

替换指定位置

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的类对应

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

与 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.

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

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.

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

创建正则对象

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'.

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

l 使用静态工厂方法

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

相关推荐
罗政14 分钟前
[附源码]超简洁个人博客网站搭建+SpringBoot+Vue前后端分离
vue.js·spring boot·后端
迷迭所归处17 分钟前
C++ —— 关于vector
开发语言·c++·算法
架构文摘JGWZ1 小时前
Java 23 的12 个新特性!!
java·开发语言·学习
leon6251 小时前
优化算法(一)—遗传算法(Genetic Algorithm)附MATLAB程序
开发语言·算法·matlab
拾光师2 小时前
spring获取当前request
java·后端·spring
锦亦之22332 小时前
QT+OSG+OSG-earth如何在窗口显示一个地球
开发语言·qt
我是苏苏2 小时前
Web开发:ABP框架2——入门级别的增删改查Demo
java·开发语言
姜太公钓鲸2332 小时前
c++ static(详解)
开发语言·c++
菜菜想进步2 小时前
内存管理(C++版)
c语言·开发语言·c++
2301_789985942 小时前
Java语言程序设计基础篇_编程练习题*18.29(某个目录下的文件数目)
java·开发语言·学习