SAP ABAP 基础与入门(一、数据类型定义与字符串处理)

目录

1.   基础

1.1.  基本数据类型

1.1.1.P类型(压缩型)数据

1.2.TYPE、LIKE

1.3.  DESCRIBE

1.4.字符串表达式

1.5.  Data element、Domain

1.6.  词典预定义类型与ABAP类型映射

1.7.字符串处理

1.7.1.   count、match结合

1.7.2. FIND …SUBMATCHES 

1.7.3.   FIND …RESULTS  itab


1.   基础

1.1.  基本数据类型

CNDTIFPXstringXstring

P:默认为8字节,最大允许16字节。最大整数位:16*2 = 32 - 1 = 31 -14(允许最大小数位数) = 17位整数位

类型

最大长度(字符数)

默认长度

说明

C

1~262143个字符

1 字符

普通字符(常用于名称、备注等字段,是最常用的类型)

N

1~262143个字符

1 字符

0到9之间字符组成的数字字符串

D

8 个字符

日期格式必须为 YYYYMMDD

T

6 个字符

格式为 24-hour的 HHMMSS

I

4 bytes

-2.147.483.648 to +2.147.483.647

F

8 bytes

小数位最大可以到17位,即可精确到小数点后17位

P

1 to 16 bytes

8 bytes

两个数字位压缩后才占一个字节,由于0-9的数字只需要4Bit位,所以一个字节实质上允许存储二位数字,这就是P数据类型为压缩数据类型的由来。并借用半个字节来存储小数点位置、正号、负号相关信息

X

1~524,287 bytes

1 byte

十六进制字符 0-9, A-F具体的范围为:00~FF

类型X是十六进制类型,可表示内存字节实际内容,使用两个十六制字符表示一个字节中所存储的内容。但直接打印输出时,输出的还是赋值时字面意义上的值,而不是Unicode解码后的字符

如果未在 DATA 语句中指定参数<length>,则创建长度为 1

注:如果值是字母,则一定要大写

1.1.1.P类型(压缩型)数据

是一种压缩的定点数,其数据对象占据内存字节数和数值范围取定义时指定的整个数据大小和小数点后位数,如果不指定小数位,则将视为I类型。其有效数字位大小可以是从1~31位数字(小数点与正负号占用一个位置,半个字节),小数点后最多允许14个数字

P类型的数据,可用于精确运算(这里的精确指的是存储中所存储的数据与定义时字面上所看到的大小相同,而不存在精度丢失问题——看到的就是内存中实实在在的大小)。在使用P类型时,要先选择程序属性中的选项 Fixed point arithmetic(即定点算法,一般默认选中),否则系统将P类型看用整型。其效率低于IF类型。

"16 * 2 = 32表示了整个字面意义上允许的最大字面个数,而14表示的是字面上小数点后面允许的最大小数位,而不是指14个字节,只有这里定义时的16才表示16个字节

DATAp(16TYPE DECIMALS 14 VALUE '12345678901234567.89012345678901'.

"正负符号与小数点固定要占用半个字节,一个字面上位置,并包括在这16个字节里面。
"16 * 2 = 32位包括了小数点与在正负号在内
"在定义时字面上允许最长可以达到32位,除去小数点与符号需占半个字节以后
"有效数字位可允许31位,这31位中包括了整数位与小数位,再除去定义时小
"数位为14位外,整数位最多还可达到17位,所以下面最多只能是179
DATAp1(16TYPE DECIMALS 14 VALUE '-99999999999999999'.

 

"P类型是以字符串来表示一个数的,与字符串不一样的是,P类型中的每个数字位只会占用4Bit位,所以两个数字位才会占用一个字节。另外,如果定义时没有指定小数位,表示是整型,但小数点固定要占用半个字节,所以不带小数位与符号的最大与最小整数如下(最多允许319,而不是32个)
DATA: p1(16TYPE p  VALUE '+9999999999999999999999999999999'.
DATA: p2(16TYPE p  VALUE '-9999999999999999999999999999999'.

 

其实P类型是以字符串形式来表示一个小数,这样才可以作到精确,就像Java中要表示一个精确的小数要使用BigDecimal一样,否则会丢失精度。

DATAp(9TYPE DECIMALS VALUE '-123456789012345.12'.

”在ABAP 中的负数是负号在右边的,想要转换可以通过函数或者代码进行转换,负号前置
WRITE/ p."123456789012345.12-

DATA f1 TYPE VALUE '2.0',
      f2 TYPE VALUE '1.1',
      f3 TYPE f.
f3  =  f1 f2."不能精确计算
"2.0000000000000000E+00 1.1000000000000001E+00 8.9999999999999991E-01
WRITE/ f1   f2 f3.

DATAp1 TYPE DECIMALS VALUE '2.0',
      p2 TYPE DECIMALS VALUE '1.1',
      p3 TYPE DECIMALS 1.
p3  =  p1 p2."能精确计算
WRITE/ p1   p2 p3. "2.0               1.1               0.9

 

Java中精确计算:

    Public static void main(String[] args) {

        System.out.println(2.0 - 1.1);// 0.8999999999999999

        System.out.println(sub(2.0, 0.1));// 1.9

    }

    Public static double sub(double v1, double v2) {

        BigDecimal b1 = new BigDecimal(Double.toString(v1));

        BigDecimal b2 = new BigDecimal(Double.toString(v2));

        return b1.subtract(b2).doubleValue();

    }

1.2.TYPELIKE

透明表(还有其它数据词典中的类型,如结构)即可看作是一种类型,也可看作是对象,所以即可使用TYPE,也可以使用LIKE:数据元素只能用type,引用表、结构、表类型可以用like

TYPES type6 TYPE mara-matnr.
TYPES type7 LIKE mara-matnr.
DATA obj6 TYPE mara-matnr.
DATA obj7 LIKE mara-matnr.

"SFLIGHT为表类型
DATA plane LIKE sflight-planetype.
DATA plane2 TYPE sflight-planetype.
DATA plane3 LIKE sflight.
DATA plane4 TYPE sflight.
"syst为结构类型
DATA sy1 TYPE syst.
DATA sy2 LIKE syst.
DATA sy3 TYPE syst-index.
DATA sy4 LIKE syst-index.

 

注:定义的变量名千万别与词典中的类型相同,否则表面上即可使用TYPE也可使用LIKE,就会出现这两个关键字(TypeLike)都可用的奇怪现像下面是定义一个变量时与词典中的结构同名的后果(导致)

DATA : BEGIN OF address2,
  street(20TYPE c,
  city(20TYPE c,
END OF address2.
DATA obj4 TYPE STANDARD TABLE OF address2."这里使用的实质上是词典中的类型address2
DATA obj5 LIKE STANDARD TABLE OF address2."这里使用是的上面定义的变量address2

上面程序编译通过,按理obj4定义是通过不过的(只能使用LIKE来引用另一定义变量的类型,TYPE是不可以的),但由于address2是数字词典中定义的结构类型,所以obj4使用的是数字词典中的结构类型,而obj5使用的是LIKE,所以使用的是address2变量的类型

1.3.  DESCRIBE

DESCRIBE FIELD dobj 
  [TYPE typ [COMPONENTS com]] 
  [LENGTH ilen IN {BYTE|CHARACTERMODE]   "固定长度
  [DECIMALS dec]                 "确定小数点位数
  [OUTPUT-LENGTH olen]  "确定输出长度
  [HELP-ID hlp] 
  [EDIT MASK mask].


DESCRIBE TABLE itab [KIND knd] [LINES lin] [OCCURS n].

解释:蓝色字体为关键字,itab自定义内表名,lin自定义变量,用于储存内表行数,n创建期间决定内表所需要的初始化内存大小

KIND knd

标识为T 时代表标准表,为S时代表排序表,为H时代表哈希表。这些值在类型组SYDES中已被定义成常量sydes_kind-standed ,sydes_kind-sorted,sydes_kind-hashed。

1.4.字符串表达式

可以使用&&&将多个字符模板串链接起来,可以突破255个字符的限制,下面两个是等效的:

|...| &  |...|

|...| && |...|

如果内容只有字面常量文本(没有变量表达式或控制字符\r \n \t),则不需要使用字符模板,可这样(如果包含了这些控制字符时,会原样输出,所以有这些控制字符时,请使用 |...|将字符包起来):

`...` && `...`

但是上面3个与下面3个是不一样的:

`...` &  `...`

'...' &  '...'

'...' && '...'

上面前两个还是会受255个字符长度限制,最后一个虽然不受255限制,但尾部空格会被忽略

字面常量文本literal text)部分,使用 ||括起来,不能含有控制字符(如 \r \n \t这些控制字符),特殊字符 |{ } \需要使用 \进行转义:

txt |Characters \|\{and \} have to be escaped by \\ in literal text.|.

字符串表达式

str |{ }|."算术计算表达式
str |{ |aa| && 'bb' }|."字符串表达式

str |{ str }|."变量名

str |{ strlenstr }|."内置函数

1.5.  Data elementDomain

数据元素是构成结构、表的基本组件,域又定义了数据元素的技术属性。Data element主要附带Search HelpParameter ID、以及标签描述,而类型是由Domain域来决定的。Domain主要从技术方面描述了Data element,如Data Type数据类型、Output Length输出长度、Convers. Routine转换规则、以及Value Range取值范围

将技术信息从Data element提取出来为Domain域的好处:技术信息形成的Domain可以共用,而每个表字段的业务含意不一样,会导致其描述标签、搜索帮助不一样,所以牵涉到业务部分的信息直接Data element中进行描述,而与业务无关的技术信息部分则分离出来形成Domain

1.6.  词典预定义类型与ABAP类型映射

当你在ABAP程序中引用了ABAPDictionary,则预置Dictionary类型则会转换为相应的ABAP类型,预置的Dictionary类型转换规则表如下:

 

Dictionarytype

Meaning

Maximumlengthn

ABAPtype

DEC

Calculation/amountfield

1-31, 1-17intables

P((n+1)/2)

INT1

Single-byte integer

3

Internalonly

INT2

Two-byteinteger

5

Internalonly

INT4

Four-byteinteger

10

I

CURR

Currencyfield货币字段

1-17

P((n+1)/2)

CUKY

Currencykey货币代码

5

C(5)

QUAN

Amount金额

1-17

P((n+1)/2)

UNIT

Unit单位

2-3

C(n)

PREC

Accuracy

2

X(2)

FLTP

Floating pointnumber

16

F(8)

NUMC

Numeritext数字字符

1-255

N(n)

CHAR

Character字符

1-255

C(n)

LCHR

Long character

256-max

C(n)

STRING

Stringofvariable length

1-max

STRING.

RAWSTRING

Byte sequence of variable length

1-max

XSTRING

DATS

Date

8

D

ACCP

Accounting period YYYYMM

6

N(6)

TIMS

Time HHMMSS

6

T

RAW

Byte sequence

1-255

X(n)

LRAW

Long byte sequence

256-max

X(n)

CLNT

Client

3

C(3)

LANG

Language

internal 1, external 2

C(1)

这里的“允许最大长度m”表示的是字面上允许的字符位数,而不是指底层所占内存字节数,如

int1的取值为0~255,所以是3位(不包括符号位)

int2的取值为-32768~32767,所以是5

lLCHR and LRAW类型允许的最大值为INT2 最大值

lRAWSTRING and STRING 具有可变长度,最大值可以指定,但没有上限

lSSTRING 长度是可变的,其最大值必须指定且上限为255。与CHAR类型相比其优势是它与ABAP type string进行映射。

这些预置的Dictionary类型在创建Data elementDomain时可以引用

Unicode系统中,一个字符占两个字节

1.7.字符串处理

SPLIT dobj AT sep INTO { {result1 result2 ...} | {TABLE result_tab} }必须指定足够目标字段。否则,用字段dobj的剩余部分填充最后目标字段并包含分界符;或者使用内表动态接收

SHIFT dobj {[{BY num PLACES}|{UP TO sub_string}][[LEFT|RIGHT][CIRCULAR]]}
           | { {LEFT DELETING LEADING}|{RIGHT DELETING TRAILING} pattern

对于固定长度字符串类型,shift产生的空位会使用空格或十六进制的0(如果为X类型串时)来填充

向右移动时前面会补空格,固定长度类型字符串与String结果是不一样:String类型右移后不会被截断,只是字串前面补相应数量的空格,但如果是C类型时,则会截断;左移后后面是否被空格要看是否是固定长度类型的字符串还是变长的String类型串,左移后C类型会补空格,String类型串不会(会缩短)

CIRCULAR:将移出的字符串放在左边或者左边

pattern:只要前导或尾部字符在指定的pattern字符集里就会被去掉,直到第一个不在模式pattern的字符止

CONDENSE <c> [NO-GAPS].如果是C类型只去掉前面的空格(因为是定长,即使后面空格去掉了,左对齐时后面会补上空格),如果是String类型,则后面空格也会被去掉;字符串中间的多个连续的空格使用一个空格替换(String类型也是这样)NO-GAPS:字符串中间的所有空格都也都会去除(String类型也是这样);空格去掉后会左对齐[kənˈdens] 

CONCATENATE {dobj1 dobj2 ...}|{LINES OF itab}[kənˈkatɪneɪt]
            INTO result
            [SEPARATED BY sep]
            [RESPECTING BLANKS].

CDNT类型的前导空格会保留,尾部空格都会被去掉,但对String类型所有空格都会保留;对于c, d, n, t类型的字符串有一个RESPECTING BLANKS选项可使用,表示尾部空格也会保留。注:使用 `` String类型进行赋值时才会保留尾部空格  字符串连接可以使用 && 来操作,具体请参考这里

strlen(arg)Xstrlen(arg)String类型的尾部空格会计入字符个数中,但C类型的变量尾部空格不会计算入

substringval TEXT [off off] [len len] )

count( val TEXT {sub substring}|{regex regex} )匹配指定字符串substring或正则式regex出现的子串次数,返回的类型为i整型类型

containsval TEXT REGEX REGEX)是否包含。返回布尔值,注:只能用在ifWhile等条件表达式中

matchesval TEXT REGEX REGEX)regex表达式要与text完全匹配,这与contains是不一样的。返回布尔值,也只能用在ifWhile等条件表达式中

matchval TEXT REGEX REGEX occ occ)返回的为匹配到的字符串。注:每次只匹配一个。occ:表示需匹配到第几次出现的子串。如果为正,则从头往后开始计算,如果为负,则从尾部向前计算

findval TEXT {sub substring}|{regex regex}[occ occ] )查找substring或者匹配regex的子串的位置。如果未找到,则返回 -1,返回的为offset,所以从0开始

FIND ALL OCCURRENCES OF REGEX regex IN  dobj
  [MATCH COUNT  mcnt]   成功匹配的次数
  { {[MATCH OFFSET moff][MATCH LENGTH mlen]}最后一次整体匹配到的串(整体串,最外层分组,而不是指正则式最内最后一个分组)起始位置与长度
  | [RESULTS result_tab|result_wa] } result_tab接收所有匹配结果,result_wa只能接收最后一次匹配结果
  [SUBMATCHES s1 s2 ...].通常与前面的MATCH OFFSET/ LENGTH一起使用。只会接收使用括号进行分组的子组。如果变量s1 s2 ...比分组的数量多,则多余的变量被initial;如果变量s1 s2 ...比分组的数量少,则多余的分组将被忽略;且只存储第一次或最后一次匹配到的结果

replaceval TEXT  REGEX REGEX  WITH NEW)使用new替换指定的子符串,返回String类型

REPLACE ALL OCCURRENCES OF REGEX regex IN  dobj WITH new

1.7.1.   countmatch结合

DATAtext TYPE string VALUE `Cathy's cat with the hat sat on Matt's mat.`,
      regx TYPE string VALUE `\<.at\>`."\< 单词开头,\> 单词结尾
DATAcounts TYPE i,
index TYPE i,
      substr TYPE string.
WRITE text.
NEW-LINE.
counts countval text regex regx )."返回匹配次数
DO counts TIMES.
index findval   text regex regx occ sy-index )."返回匹配到的的起始位置索引
  substr matchval  text regex regx occ sy-index )."返回匹配到的串
index index 1.
WRITE AT index substr.
ENDDO.

1.7.字符串处理

SPLIT dobj AT sep INTO { {result1 result2 ...} | {TABLE result_tab} }必须指定足够目标字段。否则,用字段dobj的剩余部分填充最后目标字段并包含分界符;或者使用内表动态接收

SHIFT dobj {[{BY num PLACES}|{UP TO sub_string}][[LEFT|RIGHT][CIRCULAR]]}
           | { {LEFT DELETING LEADING}|{RIGHT DELETING TRAILING} pattern

对于固定长度字符串类型,shift产生的空位会使用空格或十六进制的0(如果为X类型串时)来填充

向右移动时前面会补空格,固定长度类型字符串与String结果是不一样:String类型右移后不会被截断,只是字串前面补相应数量的空格,但如果是C类型时,则会截断;左移后后面是否被空格要看是否是固定长度类型的字符串还是变长的String类型串,左移后C类型会补空格,String类型串不会(会缩短)

CIRCULAR:将移出的字符串放在左边或者左边

pattern:只要前导或尾部字符在指定的pattern字符集里就会被去掉,直到第一个不在模式pattern的字符止

CONDENSE <c> [NO-GAPS].如果是C类型只去掉前面的空格(因为是定长,即使后面空格去掉了,左对齐时后面会补上空格),如果是String类型,则后面空格也会被去掉;字符串中间的多个连续的空格使用一个空格替换(String类型也是这样)NO-GAPS:字符串中间的所有空格都也都会去除(String类型也是这样);空格去掉后会左对齐[kənˈdens] 

CONCATENATE {dobj1 dobj2 ...}|{LINES OF itab}[kənˈkatɪneɪt]
            INTO result
            [SEPARATED BY sep]
            [RESPECTING BLANKS].

CDNT类型的前导空格会保留,尾部空格都会被去掉,但对String类型所有空格都会保留;对于c, d, n, t类型的字符串有一个RESPECTING BLANKS选项可使用,表示尾部空格也会保留。注:使用 `` String类型进行赋值时才会保留尾部空格  字符串连接可以使用 && 来操作,具体请参考这里

strlen(arg)Xstrlen(arg)String类型的尾部空格会计入字符个数中,但C类型的变量尾部空格不会计算入

substringval TEXT [off off] [len len] )

count( val TEXT {sub substring}|{regex regex} )匹配指定字符串substring或正则式regex出现的子串次数,返回的类型为i整型类型

containsval TEXT REGEX REGEX)是否包含。返回布尔值,注:只能用在ifWhile等条件表达式中

matchesval TEXT REGEX REGEX)regex表达式要与text完全匹配,这与contains是不一样的。返回布尔值,也只能用在ifWhile等条件表达式中

matchval TEXT REGEX REGEX occ occ)返回的为匹配到的字符串。注:每次只匹配一个。occ:表示需匹配到第几次出现的子串。如果为正,则从头往后开始计算,如果为负,则从尾部向前计算

findval TEXT {sub substring}|{regex regex}[occ occ] )查找substring或者匹配regex的子串的位置。如果未找到,则返回 -1,返回的为offset,所以从0开始

FIND ALL OCCURRENCES OF REGEX regex IN  dobj
  [MATCH COUNT  mcnt]   成功匹配的次数
  { {[MATCH OFFSET moff][MATCH LENGTH mlen]}最后一次整体匹配到的串(整体串,最外层分组,而不是指正则式最内最后一个分组)起始位置与长度
  | [RESULTS result_tab|result_wa] } result_tab接收所有匹配结果,result_wa只能接收最后一次匹配结果
  [SUBMATCHES s1 s2 ...].通常与前面的MATCH OFFSET/ LENGTH一起使用。只会接收使用括号进行分组的子组。如果变量s1 s2 ...比分组的数量多,则多余的变量被initial;如果变量s1 s2 ...比分组的数量少,则多余的分组将被忽略;且只存储第一次或最后一次匹配到的结果

replaceval TEXT  REGEX REGEX  WITH NEW)使用new替换指定的子符串,返回String类型

REPLACE ALL OCCURRENCES OF REGEX regex IN  dobj WITH new

1.7.1.   countmatch结合

DATAtext TYPE string VALUE `Cathy's cat with the hat sat on Matt's mat.`,
      regx TYPE string VALUE `\<.at\>`."\< 单词开头,\> 单词结尾
DATAcounts TYPE i,
index TYPE i,
      substr TYPE string.
WRITE text.
NEW-LINE.
counts countval text regex regx )."返回匹配次数
DO counts TIMES.
index findval   text regex regx occ sy-index )."返回匹配到的的起始位置索引
  substr matchval  text regex regx occ sy-index )."返回匹配到的串
index index 1.
WRITE AT index substr.
ENDDO.

1.7.2. FIND …SUBMATCHES 

DATAmoff TYPE i,
       mlen TYPE i,
       s1   TYPE string,
       s2   TYPE string,
       s3   TYPE string,
       s4   TYPE string.
FIND ALL OCCURRENCES OF REGEX `((\w+)\W+\2\W+(\w+)\W+\3)`"\2 \3 表示反向引用前面匹配到的第二与第三个子串
IN `Hey hey, my my, Rock and roll can never die Hey hey, my my`"会匹配二次,但只会返回第二次匹配到的结果,第一次匹配到的子串不会存储到s1s2s3中去
IGNORING CASE
MATCH OFFSET moff
 MATCH LENGTH mlen
SUBMATCHES s1 s2 s3 s4."根据从外到内,从左到右的括号顺序依次存储到s1 s2…中,注:只取出使用括号括起来的子串,如想取整体子串则也要括起来,这与Java不同
WRITE/  s1/ s2,/ s3 ,/ s4,/ moff ,/ mlen."s4会被忽略

1.7.3.   FIND …RESULTS  itab

DATAresult TYPE STANDARD TABLE OF string WITH HEADER LINE .
"Java不同,只要是括号括起来的都称为子匹配(即使用整体也用括号括起来了),
"不管括号嵌套多少层,统称为子匹配,且匹配到的所有子串都会存储到,
"MATCH_RESULT-SUBMATCHES中,即使最外层的括号匹配到的子串也会存储到SUBMATCHES 
"内表中。括号解析的顺序为:从外到内,从左到右的优先级顺序来解析匹配结构。
"Java中的group(0)存储的是整体匹配串,即使整体未(或使用)使用括号括起来
PERFORM get_match TABLES result
USING '2011092131221032' '(((\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.
DATAresult_tab TYPE match_result_tab WITH HEADER LINE.
DATAsubresult_tab TYPE submatch_result_tab WITH HEADER LINE.
"注意:带表头时 result_tab 后面一定要带上中括号,否则激活时出现奇怪的问题
FIND ALL OCCURRENCES OF REGEX p_reg IN p_str RESULTS result_tab[].
"result_tab中存储了匹配到的子串本身(与Regex整体匹配的串,存储在
"result_tab-offsetresult_tab-length中)以及所子分组(括号部分,存储在
"result_tab-submatches中)
LOOP AT result_tab .
"如需取整体匹配到的子串(与Regex整体匹配的串),则使用括号将整体Regex括起来
"来即可,括起来后也会自动存储到result_tab-submatches,而不需要在这里像这样读取
*    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.

1.7.2. FIND …SUBMATCHES 

DATAmoff TYPE i,
       mlen TYPE i,
       s1   TYPE string,
       s2   TYPE string,
       s3   TYPE string,
       s4   TYPE string.
FIND ALL OCCURRENCES OF REGEX `((\w+)\W+\2\W+(\w+)\W+\3)`"\2 \3 表示反向引用前面匹配到的第二与第三个子串
IN `Hey hey, my my, Rock and roll can never die Hey hey, my my`"会匹配二次,但只会返回第二次匹配到的结果,第一次匹配到的子串不会存储到s1s2s3中去
IGNORING CASE
MATCH OFFSET moff
 MATCH LENGTH mlen
SUBMATCHES s1 s2 s3 s4."根据从外到内,从左到右的括号顺序依次存储到s1 s2…中,注:只取出使用括号括起来的子串,如想取整体子串则也要括起来,这与Java不同
WRITE/  s1/ s2,/ s3 ,/ s4,/ moff ,/ mlen."s4会被忽略

1.7.3.   FIND …RESULTS  itab

DATAresult TYPE STANDARD TABLE OF string WITH HEADER LINE .
"Java不同,只要是括号括起来的都称为子匹配(即使用整体也用括号括起来了),
"不管括号嵌套多少层,统称为子匹配,且匹配到的所有子串都会存储到,
"MATCH_RESULT-SUBMATCHES中,即使最外层的括号匹配到的子串也会存储到SUBMATCHES 
"内表中。括号解析的顺序为:从外到内,从左到右的优先级顺序来解析匹配结构。
"Java中的group(0)存储的是整体匹配串,即使整体未(或使用)使用括号括起来
PERFORM get_match TABLES result
USING '2011092131221032' '(((\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.
DATAresult_tab TYPE match_result_tab WITH HEADER LINE.
DATAsubresult_tab TYPE submatch_result_tab WITH HEADER LINE.
"注意:带表头时 result_tab 后面一定要带上中括号,否则激活时出现奇怪的问题
FIND ALL OCCURRENCES OF REGEX p_reg IN p_str RESULTS result_tab[].
"result_tab中存储了匹配到的子串本身(与Regex整体匹配的串,存储在
"result_tab-offsetresult_tab-length中)以及所子分组(括号部分,存储在
"result_tab-submatches中)
LOOP AT result_tab .
"如需取整体匹配到的子串(与Regex整体匹配的串),则使用括号将整体Regex括起来
"来即可,括起来后也会自动存储到result_tab-submatches,而不需要在这里像这样读取
*    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.

1.7.4.正则式类

regex = Regular expression   [ˈreɡjulə]

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

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

1.7.4.1.matchesmatch

是否完全匹配(正则式中不必使用 ^  $);matches为静态方法,而match为实例方法,作用都是一样

DATAmatcher TYPE REF TO cl_abap_matcher,
      match TYPE match_result,
      match_line TYPE submatch_result.
"^$可以省略因为matches方法本身就是完全匹配整个Regex
IF cl_abap_matcher=>matchespattern '^(db(ai).*)$' text 'dbaiabd' ) = 'X'.
  matcher cl_abap_matcher=>get_object( )."获取最后一次匹配到的 Matcher 实例
  match matcher->get_match( ). "获取最近一次匹配的结果(是整体匹配的结果)
WRITE / matcher->text+match-offset(match-length).
LOOP AT  match-submatches INTO match_line"提取子分组括号括起来的部分
WRITE/20 match_line-offsetmatch_line-length,matcher->text+match_line-offset(match_line-length).
ENDLOOP.
ENDIF.

DATAmatcher TYPE REF TO cl_abap_matcher,
      match TYPE match_result,
      match_line TYPE submatch_result.
"^$可以省略,因为matche方法本身就是完全匹配整个Regex
matcher cl_abap_matcher=>createpattern '^(db(ai).*)$' text 'dbaiabd' ).
IF matcher->match(  ) = 'X'.
  match matcher->get_match( ). "获取最近一次匹配的结果
WRITE / matcher->text+match-offset(match-length).
LOOP AT  match-submatches INTO match_line"提取子分组(括号括起来的部分)
WRITE/20 match_line-offsetmatch_line-length,matcher->text+match_line-offset(match_line-length).
ENDLOOP.
ENDIF.

1.7.4.2.contains

是否包含(也可在正则式中使用 ^  $ 用于完全匹配检查,或者使用 ^ 检查是否匹配开头,或者使用 $ 匹配结尾)

DATAmatcher TYPE REF TO cl_abap_matcher,
      match TYPE match_result,
match_line TYPE submatch_result.
IF cl_abap_matcher=>containspattern '(db(ai).{2}b)' text 'dbaiabddbaiabb' ) = 'X'.
  matcher cl_abap_matcher=>get_object( ). "获取最后一次匹配到的 Matcher 实例
  match matcher->get_match( ). "获取最近一次匹配的结果
WRITE / matcher->text+match-offset(match-length).
  LOOP AT  match-submatches INTO match_line"提取子分组(括号括起来的部分)
WRITE/20 match_line-offsetmatch_line-length,matcher->text+match_line-offset(match_line-length).
ENDLOOP.
ENDIF.

1.7.4.3.find_all

一次性找出所有匹配的子串,包括子分组(括号括起的部分)

DATAmatcher TYPE REF TO cl_abap_matcher,
       match_line TYPE submatch_result,
      itab TYPE match_result_tab WITH HEADER LINE.
matcher cl_abap_matcher=>createpattern '<[^<>]*(ml)>' text '<html>hello</html>' )."创建 matcher 实例
"注:子分组存储在itab-submatches字段里
itab[] matcher->find_all( ).
LOOP AT itab .
WRITE/ matcher->textitab-offsetitab-length,matcher->text+itab-offset(itab-length).
  LOOP AT  itab-submatches INTO match_line"提取子分组(括号括起来的部分)
WRITE/20 match_line-offsetmatch_line-length,matcher->text+match_line-offset(match_line-length).
ENDLOOP.
ENDLOOP.

1.7.4.4.find_next

逐个找出匹配的子串,包括子分组(括号括起的部分)

DATAmatcher TYPE REF TO cl_abap_matcher,
      match TYPE match_resultmatch_line TYPE submatch_result,
      itab TYPE match_result_tab WITH HEADER LINE.
matcher cl_abap_matcher=>createpattern '<[^<>]*(ml)>' text '<html>hello</html>' ).
WHILE matcher->find_next( ) = 'X'.
  match matcher->get_match( )."获取最近一次匹配的结果
WRITE/ matcher->textmatch-offsetmatch-length,matcher->text+match-offset(match-length).  
  LOOP AT  match-submatches INTO match_line. "提取子分组(括号括起来的部分)
 WRITE/20 match_line-offsetmatch_line-length,matcher->text+match_line-offset(match_line-length).
  ENDLOOP.
ENDWHILE.

1.7.4.5.get_lengthget_offsetget_submatch

DATAmatcher TYPE REF TO cl_abap_matcher,
      length TYPE i,offset TYPE i,
      submatch TYPE string.
matcher cl_abap_matcher=>createpattern '(<[^<>]*(ml)>)' text '<html>hello</html>' ).
WHILE matcher->find_next( ) = 'X'. "循环2
"0时,表示取整个Regex匹配到的子串,这与Java一样,但如果整个Regex使用括号括起来后,
"则分组索引为1,这又与Java不一样(Java不管是否使用括号将整个Regex括起来,分组索引号都为0
  "上面Regex中共有两个子分组,再加上整个Regex为隐含分组,所以一共为3
DO TIMES.
"在当前匹配到的串(整个Regex相匹配的串)中返回指定子分组的匹配到的字符串长度
    length matcher->get_lengthsy-index ).
"在当前匹配到的串(整个Regex相匹配的串)中返回指定子分组的匹配到的字符串起始位置
    offset matcher->get_offsetsy-index ).
"在当前匹配到的串(整个Regex相匹配的串)中返回指定子分组的匹配到的字符串
    submatch matcher->get_submatchsy-index ).
WRITE:/ length offset,matcher->text+offset(length),submatch.
ENDDO.
SKIP.
ENDWHILE.

1.7.4.6.replace_all

DATAmatcher TYPE REF TO cl_abap_matcher,
      count TYPE i,
      repstr TYPE string.
matcher cl_abap_matcher=>createpattern '<[^<>]*>' text '<html>hello</html>' ).
count matcher->replace_all``)."返回替换的次数
repstr matcher->text. "获取被替换后的新串
WRITEcount repstr.

        

  • 22
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值