字符串處理: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 \n \r \t \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

.+\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, $&

整個匹配

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\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-$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

\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類型的字符串或者內容爲空格的固定長度類型(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+\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個變量,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+\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類型的字符串或者內容爲空格的固定長度類型(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]

相關文章
相關標籤/搜索