字符串处理 语句、函数
字符串处理
“空字符”、“空字符串”、''与``
'':表示的是不 empty 字符,属于C(1)固定长度字符类型,是一个空格。所以'' = space
``:表示的是一个empty字符,属于String类型,但如果将它赋值给一个C(1)类型变量后,感觉 `` 是一个空格,这实质上是一种误解,这是因为 `` 本身是一个 empty 字符(表示什么也没有,即没有任何内容),但如果此时赋值给一个 C(1) 类型的变量时,会发生基本类型赋值规则转换:String→C(按此转换规则,源String字段长度为0,所以使用空格来填充目标C字段)
0 1 0 0 0 0
为什么''=`` ?
''属于固定长度的C类型字符串,而``属于变量的String类型字符串,当`` = ''放在if语句中进行比较时,会发生类型转换(转换规则为不同类型数据之间的转换):相当于将C(1)固定长度字符串(内容为一个空格)转换为String类型变量字符串,在转换过程中按C→String规则:尾部空格会去掉(相当于 str = '',最后还是一个empty字符串),所以`` = ''为真,这也解释了为什么strlen( '' ) = 0 而不是等于1为原因(因为在计算前''也会转换为 String类型后再进行计算,在转换过程中会将C类型字符串尾部空格去掉)。
在给String类型变量赋值时,最好使用``将字符串引起来,这样尾部空格不会去掉,因为没有发生类型转换;而将''单引号引起来的C类型类型串赋值给一个String类型变量时,会发生类型转换(C类型会转换为String),在转换过程中会忽略C类型尾部空格。
字符型字面常量(Text Symbols文本符号)
字符型字面常量是使用单引号''起来的字符串,它其实是一种C类型的字面常量,所以赋值给C类型的变量时,不会发生类型转换什么的。注:没有空的字符型字面常量,也就是说,即使使用'' 来想表达“空”的概念,也是不允许的,它实质上是一个空格的字面常量,即与' '完全相同
使用两个单引号''引起来的字符型字面常量的个数一定不能超过255个,否则编译不能通过。如果需要将多个字符型字面常量连接起来当作一个字符型常量,则可以使用&字符将多个使用单引号(注:使用&连接的串要么是字符型字面常量——使用单引号引起来的串,要么是字符串型字面常量——使用反引号引起来的串,两者不能混着使用,否则编译不能通过)引起来的字符型字面常量连接起来,但总体的长度还是不能大于255个
文本符号
如果使用单引号''(不是``)引起来的字面常量后面跟了三位数编号,则会先去所对应程序的文本符号中去找这个编号对应的文本是否存在,如果存在则使用文本符号中的文本,否则使用单引号''中的字面常量:
或者上图中使用WRITE: text-001.效果也是一样的
字符串型字面常量
字符型字面常量是使用反引号``引起来的字符串,它是一种String类型的字面常量。如果两个反引号之间没有任何内容,即 `` 表示是一个长度为0的空字符串,这与两个单引号''之间没有任何内容但实质上还是有一个空格是有区别的。
使用两个反引号``引起来的字符串型字面常量的个数一定不能超过255个,否则编译不能通过。如果需要将多个字符串型字面常量连接起来当作一个字符串型常量,则可以使用&字符将多个使用反引号(注:使用&连接的串要么是字符型字面常量——使用单引号引起来的串,要么是字符串型字面常量——使用反引号引起来的串,两者不能混着使用,否则编译不能通过)引起来的字符串型字面常量连接起来,但总体的长度还是不能大于255个
C(1)空字符
split拆分字符串
SPLIT dobj AT sep INTO
{ {result1 result2 ...} | {TABLE result_tab} }
[IN {CHARACTER|BYTE} MODE].
要将所有部分放到不同目标字段中,必须指定足够目标字段。否则,用字段dobj的剩余部分填充最后目标字段并包含分界符。
如果所有目标字段足够长且不必截断任何拆分的字符串就可以容纳,则将 SY-SUBRC 设置为0。
DATA: string(60),
p1(20) VALUE '++++++++++++++++++++',
p2(20) VALUE '++++++++++++++++++++',
p3(20) VALUE '++++++++++++++++++++',
p4(20) VALUE '++++++++++++++++++++',
del(3) VALUE '***'.
string = ' Part 1 *** Part 2 *** Part 3 *** Part 4 *** Part 5'.
WRITE string.
SPLIT string AT del INTO p1 p2 p3 p4.
WRITE / p1.
WRITE / p2.
WRITE / p3.
WRITE / p4.
Part 1 *** Part 2 *** Part 3 *** Part 4 *** Part 5
Part 1
Part 2
Part 3
Part 4 *** Part 5
可以将拆分的字符串放到一个内表中,这样就不需要定义多个目标字段了,该内表就好比是一个数组,而且可以自动增长,并且该内表只有一个组件元素:
DATA: string(60) VALUE ' Part 1 *** Part 2 *** Part 3 *** Part 4 *** Part 5'.
DATA: itab TYPE TABLE OF string,wa like LINE OF itab.
SPLIT string AT '***' INTO TABLE itab .
LOOP AT itab INTO wa.
WRITE: / wa.
ENDLOOP.
Part 1
Part 2
Part 3
Part 4
Part 5
segment()函数
segment( val = text index = idx [sep|space = sep] )
根据指定的字符串sep或者指定的字符sapce来将text拆分,并返回第idx(从1开始)个片断
sep:为分隔字符串,整个sep会当作分界符,如果text中两个sep分隔字符串紧挨着时,empty segment is created and an empty string is returned for this segment
space:与sep不同的是,sapce是一个字符集,分隔符不是整个sapce,而是sapce里的每个字符都是一个分界符,即分界符是单个字符,只不过sapce可以同时指定多个分隔符组成一个字符集。另外,与sep不同的是,如果sapce中指定的分隔符紧挨着时,no empty segment is created and no result is returned.
DATA: result TYPE string,
text TYPE string VALUE 'AB\brCD\br\brEF\brGH'.
WRITE: text.
NEW-LINE.
DO.
TRY.
result = segment( val = text
index = sy-index "返回第几个片断,从1开始,不能越界,否则抛异常
sep = `\br` ).
WRITE: result.
CATCH cx_sy_strg_par_val.
EXIT.
ENDTRY.
ENDDO.
NEW-LINE.
text = 'AB CD - EF _ - GH'.
WRITE: / text.
NEW-LINE.
DO.
TRY.
result = segment( val = text
index = sy-index
space = ` -_` )."三个分隔符
WRITE: result.
CATCH cx_sy_strg_par_val.
EXIT.
ENDTRY.
ENDDO.
AB\brCD\br\brEF\brGH
AB CD EF GH
AB CD - EF _ - GH
AB CD EF GH
shift字符串移动
默认情况下,对于固定长度字符串类型,shift产生的空位会使用空格或十六进制的0(如果为X类型串时)来填充。
{[{BY num PLACES}|{UP TO sub_string}][[LEFT|RIGHT] [CIRCULAR]]}
|
{ {LEFT DELETING LEADING}|{RIGHT DELETING TRAILING} } pattern
]
[IN {BYTE|CHARACTER} MODE].
注:如果dobj为X或XString时,则只能使用IN BYTEMODE
BY num PLACES:
如果指定移动的位数大于了源字符串长度或等于0,则源字符串不会发生改变。
UP TO sub_string:
如果找到子串,则sy-subrc = 0,否则为4。
将源字符串移动到指定的子字符串位置,要注意的是向右移动时,固定长度类型字符串与String结果是不一样(String类型右移后不会被截断,只是字串前面补相应数量的空格)。
DATA text TYPE string .
text = `I know you know `.
WRITE: / text.
SHIFT text UP TO 'you' LEFT.
WRITE: / text.
text = `I know you know `.
"由于是字符串类型,其长度不是固定的,所以向右移动时,不会截断子串后面的字符串,但如果是C类型时,则会截断
SHIFT text UP TO 'you' RIGHT.
WRITE: / text.
DATA text2(16) TYPE c VALUE `I know you know `.
SHIFT text2 UP TO 'you' RIGHT.
WRITE: / text2.
I know you know
you know
I know you know
I know you
[LEFT|RIGHT][CIRCULAR]:
如果未指定LEFT or RIGHT,则默认为LEFT。CIRCULAR选项将移出的字符串放在左边或者左边。
对于String与Xstring类型,使用左移时并且如果未指定CIRCULAR,字符串将会被缩短,但右移后会延长(缩短与延长的长度与左移或右移的位数相同)。
DATA text TYPE string VALUE `I know you know `.
WRITE: / text.
SHIFT text UP TO 'you' LEFT CIRCULAR.
WRITE: / text.
text = `I know you know `.
SHIFT text UP TO 'you' RIGHT CIRCULAR.
WRITE: / text.
I know you know
you know I know
know I know you
{ {LEFT DELETING LEADING}|{RIGHT DELETING TRAILING} } pattern:
向左移出前导(或向右移出尾部)匹配pattern模式的字符串(只要前导或尾部字符在指定的pattern字符集里就会被去掉,直到第一个不在模式pattern的字符止)。右移后前面会补空格,左移后后面是否被空格要看是否是固定长度类型的字符串还是变长的String类型串(左移后String类型串会缩短)。
DATA text TYPE string VALUE `I know you know`.
WRITE: / text.
"只要是 [no kw] 这五个字符都会被去掉
SHIFT text RIGHT DELETING TRAILING 'no kw'.
WRITE: / text.
text = `I know you know`.
SHIFT text LEFT DELETING LEADING 'kI '.
WRITE: / text.
I know you know
I know you
now you know
replace字符串替换
返回码:
0 ——替换成功,并且结果未被截断
2 ——替换成功,但结果右边被截断
4 ——未找到要替换的字符串
替换指定的字符串(老式的,已过时的)
REPLACE sub_string WITH new INTO dobj
[IN {BYTE|CHARACTER} MODE]
[LENGTH len].
在dobj中查找第一次出现的sub_string字符串。首先在dobj中搜索子串 sub_string 前 len个字符,如果未定长度len,则按sub_string 全长进行搜索;当第一次发现sub_string或sub_string的前len个字符,则sub_string或sub_string的前len字符在字符串dobj中第一次出现的位置用字符串 new替换,如果指定了len,则只替换dobj指定的长度len。
如果未指定长度len,则使用new替换换整个被匹配到的子串;如果len为0,则匹配到的子串不会被替换,并且替换的内容new 会插入到匹配到的子字符串sub_string的前面;如果len比sub_string要长,默认会等于sub_string长度。
如果sub_string为空(``)字符串,则会将new插入到dobj最前面;如果为'',则不会这样。``表示字符间隙,为空字符串,而''实际上则表示一个空格:
DATA: text TYPE String VALUE 'aaabbbccc'.
REPLACE '' WITH 'ddd' INTO text.
WRITE: / text.
REPLACE `` WITH 'ddd' INTO text.
WRITE: / text.
aaabbbccc
dddaaabbbccc
如果dobj, sub_string and new的类型为 c, d, n or t固定长度类型时,尾部的空格将不会被忽略
SY-SUBRC非 0 的返回代码值意味着未替换,这样就可以使用循环方式替换所有:
DATA name TYPE string.
name = 'Mic-hael-Cheo-ng'.
WHILE sy-subrc = 0.
REPLACE '-' WITH ' ' INTO name.
ENDWHILE.
WRITE / name.
Mic hael Cheo ng
替换某个区间上的字符串
REPLACE SECTION [OFFSET off] [LENGTH len] OF dobj WITH new
[IN {BYTE|CHARACTER} MODE].
OFFSET or LENGTH必须要指定一个,如果指定了OFFSET,但未指定LENGTH时,替换的内容从OFFSET到dobj的最后;如果指定了LENGTH,但未指定OFFSET时,OFFSET将隐含为0。OFFSET与LENGTH需要大于或等于0,通过OFFSET与LENGTH定位到的子字符串段必须要位于dobj里。
该函数一般与FIND函数结合使用:
DATA: text1 TYPE string,
off TYPE i,
len TYPE i.
text1 = 'I know you know'.
FIND 'know' IN text1 MATCH OFFSET off
MATCH LENGTH len.
WRITE: / text1.
REPLACE SECTION OFFSET off LENGTH len OF
text1 WITH 'should know that'.
WRITE: / text1.
I know you know
I should know that you know
第三种是基于用正则表达式的替换,请参考后面正则表达式REPLACE
replace()函数regex
replace( val = text [off = off] [len = len] with = new )
replace( val = text {sub = substring}|{regex = regex} with = new [case = case] [occ = occ] )
使用new替换指定的子符串,返回String类型。
off、len:offset off and the length len,这两个至少要输入一个。如果仅指定off或者指定了len但为0时,相当于insert()函数;如果仅指定了len或者指定了off但为0时,会将text开头的len个字符替换为new;如果off为text的长度,则此时的len只能是0或者省略,此时的new会append到text尾部。
occ:替换第几次出现的子串,如果为0,则所有出现的都会被替换
另外,如果使用了regex模式,则new中可以使用替换模式(如$0 $1 $&…)
DATA: html TYPE string,
repl TYPE string.
html = `<title>This is the <i>Title</i></title>`.
WRITE: / html.
repl = `i`.
"repl = `(i)`."结果会是一样
html = replace( val = html
regex = repl && `(?![^<>]*>)`"注:SAP反向搜索(?<=...)、(?<!...)目前不支持,只支持正向搜索(?=...)、(?!...),但Java都支持
with = `<b>$0</b>`"$0为匹配到的整个捕获组,这与Java一样,所以也可以将 i 使用()括起来
occ = 0 ).
WRITE: / html.
<title>This is the <i>Title</i></title>
<title>Th<b>i</b>s <b>i</b>s the <i>T<b>i</b>tle</i></title>
search搜索字符串
SEARCH <c> FOR <str> <options>.
该语句在字符串<c>中搜索<str>中的字符串。如果成功,则将 SY-SUBRC 的返回代码值为0,并将 SY-FDPOS 设置为字段<c>中该字符串的位置(字符串索引位置是从0开始的)。
搜索串<str>可为下列格式之一:
<str> |
目的 |
<pattern> |
搜索<pattern>,忽略<pattern>尾部空格。 |
.<pattern>. |
搜索<pattern>,但是不忽略<pattern>尾部空格。 |
*<pattern> |
搜索以<pattern>结尾的词。 |
<pattern>* |
搜索以<pattern>开始的词。 |
单词之间用空格、逗号、句号、分号、冒号、问号、叹号、括号、斜杠、加号和等号等分隔。
DATA string(30) VALUE 'This is a little sentence.'.
WRITE: / 'Searched', 'SY-SUBRC', 'SY-FDPOS'.
ULINE /1(26).
SEARCH string FOR 'X'.
WRITE: / 'X', sy-subrc UNDER 'SY-SUBRC',
sy-fdpos UNDER 'SY-FDPOS'.
SEARCH string FOR 'itt '.
WRITE: / 'itt ', sy-subrc UNDER 'SY-SUBRC',
sy-fdpos UNDER 'SY-FDPOS'.
SEARCH string FOR '.e .'.
WRITE: / '.e .', sy-subrc UNDER 'SY-SUBRC',
sy-fdpos UNDER 'SY-FDPOS'.
SEARCH string FOR '*e'.
WRITE: / '*e', sy-subrc UNDER 'SY-SUBRC',
sy-fdpos UNDER 'SY-FDPOS'.
SEARCH string FOR 's*'.
WRITE: / 's*', sy-subrc UNDER 'SY-SUBRC',
sy-fdpos UNDER 'SY-FDPOS'.
Searched SY-SUBRC SY-FDPOS
————————————
X 4 0
itt 0 11
.e . 0 15
*e 0 10
s* 0 17
<options>选项:
n ABBREVIATED:在字符串<c>中搜索包含<str>中指定字符串的单词(<str>好比缩写),包含<str>的单词和字符串<str>中的第一个字母必须相同。
n STARTING AT <n1>:在字符串<c>中搜索从<n1>开始的<str>。结果 SY-FDPOS 参照相对于<n1>的偏移量而不是字符的开始。
n ENDING AT <n2>:在字符<c>搜索<str>直到位置<n2>。
n AND MARK:如果找到搜索串,则将搜索串中的所有字符(和使用 ABBREVIATED 时的所有字符)转换为大写形式。
DATA: string(30) VALUE 'This is a fastx first example.',
pos TYPE i,
off TYPE i.
WRITE / string.
"STARTING AT选项是从1开始的,但字符串位置索引是从0开始的
"STARTING AT选项默认就是1,并且查找时从(包括)第1个字符开始
"ENDING AT选项指定的位置结束(也包括),查找时会在这指定的区间(包括两端)
"进行搜索,如果将下面的14修改成13则会找到不到
SEARCH string FOR 'fst' ABBREVIATED STARTING AT 1ENDING AT 14.
"与上面语句等价
*SEARCH string FOR 'fst' ABBREVIATED.
"SY-FDPOS的值是指所查找到的位置的索引(如果指定了STARTING AT,则STARTING AT指定位置的字符就表示索引为0的字符)
WRITE: / 'SY-FDPOS:', sy-fdpos.
"求查找到的首字符在整个字符串中的索引号,注:索引是从0开始的
off = sy-fdpos.
WRITE: / 'Off:', off.
"第二次查找位置从fastx中的a字母(包括)开始的
pos = sy-fdpos + 2.
SEARCH string FOR 'fst' ABBREVIATED STARTING AT pos AND MARK.
WRITE / string.
WRITE: / 'SY-FDPOS:', sy-fdpos, sy-subrc.
off = pos – 1+ sy-fdpos.
WRITE: / 'Off:', off.
This is a fastx first example.
SY-FDPOS: 10
Off: 10
This is a fastx FIRST example.
SY-FDPOS: 5 0
Off: 16
请注意,在找到单词‘fastx’之后,为了查找包含‘ft’的第二个单词,必须在偏移量 SY-FDPOS 上加2(如果是加1还是找第一个,因为STARTING AT选项在查找时会包括pos位置所在字符),然后从位置 POS 开始查找。否则,会再次找到单词‘fastx’。要获得‘first’相对于字符串<c>开始的偏移量,则要使用 pos + sy-fdpos – 1 表达式来计算。
contains()函数regex
contains( val = text sub|start|end = substring [case = case] [off = off] [len = len] [occ = occ] )
在text 字符串指定的搜索区域(off开始len个字符)内搜索是否存在substring子串至少occ次,如果是则返回true。start、start分别表示在指定区域的开头或末尾是否区别(此时occ也可指定,表示在头或尾连续多次出现),而sub则可以出现在指定区域的任何位置。occ默认值都为0(包括下面其它函数也是)。substring不能为empty。
case:默认大小写敏感,X表示区分
contains( val = text regex = regex [case = case] [off = off] [len = len] [occ = occ] )
与上面的contains函数一样,只不过变成了regex
contains_any_of( val = text sub|start|end = substring [off = off] [len = len] [occ = occ] )
与上面两个不同的是,不会检查整个substring是否匹配,而是把substring看作是一个字符集,只要这里的任意一个字符在指定的搜索区域内出现过,就算一次。sub|start|end的意思与上面的一样
contains_any_not_of( val = text sub|start|end = substring [off = off] [len = len] [occ = occ] )
与contains_any_of函数相似,只不过是相反的,只要substring所有单个字符都不出现在指定搜索区域内时,则算一次
上面这些函数只能使用在 if where 等条件语句中
下面几个与过去的字符串比较操作符作用相同:
字符串比较操作符 |
等同于 |
o1 CO o2 |
NOTcontains_any_not_of( val = o1 sub = o2 ) |
o1 CN o2 |
contains_any_not_of( val = o1 sub = o2 ) |
o1 CA o2 |
contains_any_of( val = o1 sub = o2 ) |
o1 NA o2 |
NOTcontains_any_of( val = o1 sub = o2 ) |
o1 CS o2 |
contains( val = to_upper( o1 ) sub = to_upper( o2 ) ) |
o1 NS o2 |
NOT contains( val = to_upper( o1 ) sub = to_upper( o2 ) ) |
由于CS、NS是不区分大小写的,所以先全转大写(或小写)。如果使用函数的形式,则固定长度字符类型的尾部空格会被忽略掉,但字符串比较操作符有可能不太一样,在使用时需注意。
CP 、NP两个比较操作符可以使用regex的contains函数
DATA html TYPE string.
html = '<body>Text</body>'.
IF contains_any_not_of( val = to_upper( html ) start = sy-abcde ) AND
contains_any_not_of( val = to_upper( html ) end = sy-abcde ).
WRITE:/ '是 HTML 格式的字符串'.
ENDIF.
是 HTML 格式的字符串
matches()函数regex
matches( val = text regex = regex [case = case] [off = off] [len = len] )
text是否与regex匹配(regex表达式要与text完全匹配,这与contains是不一样的)。off与len指定了匹配的区域。
注:该函数与contains函数一样,也只能在 if where 条件语句中使用。matches()只是判断是否匹配,返回匹配与否,而matche()函数返回匹配到的子串
IF matches( val = sy-abcde regex = `[A-Z]{26,26}` ).
WRITE: / 'OK'.
ENDIF.
OK
count()函数regex
count( val = text {sub = substring}|{regex = regex} [case = case] [off = off] [len = len] )
匹配指定字符串substring或正则式regex出现的子串次数。返回的类型为i整型类型
case:是否大小写敏感。省略时默认是大小写敏感的。'X'表示区别大小写,' '表示不区别大小写
off、len:offset off and the length len,指定了搜索的区域,即从哪里开始搜索,并且搜索多长
count_any_of( val = text sub = substring [off = off] [len = len] )
匹配指定字符集substring中任意字符的次数。
DATA: text TYPE c LENGTH 120 VALUE `Cathy's cat with the hat sat on Matt's mat.`,
substring TYPE c LENGTH 120 VALUE `oat`.
DATA: result TYPE i.
result = count_any_of( val = text sub = substring ).
WRITE / result .
16
count_any_not_of( val = text sub = substring [off = off] [len = len] )
匹配指定字符集substring中所有均未出现的字符次数
DATA: text TYPE string VALUE `Cathy's cat with the hat sat on Matt's mat.`,
substring TYPE string VALUE `oat`.
DATA: result TYPE i.
result = count_any_not_of( val = text sub = substring off = 32 ).
WRITE / result .
6
find()函数regex
find( val = text {sub = substring}|{regex = regex} [case = case] [off = off] [len = len] [occ = occ] )
查找substring或者匹配regex的子串的位置。返回的类型为i整型类型。如果未找到,则返回 -1,返回的为offset,所以从0开始。
occ:表示需匹配到第几次出现的子串。如果为正,则从头往后开始计算,如果为负,则从尾部向前计算,比如为1、2时,分别表示只匹配到从左往右数第1次或第2次的子串,如果为-1、-2时,则分别表示只匹配到从右往左数第1次或第2次的子串。省略时默认只取最开始的第一个。
find_end( val = text regex = regex [case = case] [off = off] [len = len] [occ = occ] )
与find类似,只不过返回的不是regex匹配到串的开头字符的offset位置,而是regex匹配到串的末尾字符的offset位置
find_any_of( val = textsub = substring [off = off] [len = len] [occ = occ] )
找出text中出现substring中的任何一个字符的位置offset
DATA: text TYPE c LENGTH 120 VALUE `Cathy's cat with the hat sat on Matt's mat.`,
substring TYPE c LENGTH 120 VALUE `oat`.
DATA: result TYPE i.
result = find_any_of( val = text sub = substring )."匹配 a 字符
WRITE / result .
result = find_any_of( val = text sub = substring off = 17 )."匹配 t 字符
WRITE / result .
result = find_any_of( val = text sub = substring off = 26 )."匹配 o 字符
WRITE / result .
1
17
26
find_any_not_of( val = text sub = substring [off = off] [len = len] [occ = occ] )
找出text中未出现substring中所有字符集的起始位置offset,与find_any_of对应
DATA: text TYPE c LENGTH 120 VALUE `Cathy's cat with the hat sat on Matt's mat.`,
substring TYPE c LENGTH 120 VALUE `oat`.
DATA: result TYPE i.
result = find_any_not_of( val = text sub = substring ).
WRITE / result .
result = find_any_not_of( val = text sub = substring off = 17 ).
WRITE / result .
result = find_any_not_of( val = text sub = substring off = 26 ).
WRITE / result .
0
18
28
match()函数regex
match( val = text regex = regex [case = case] [occ = occ] )
返回的为匹配到的字符串。注:每次只匹配一个。请注意这个函数与matches()函数的区别
case:请参考count()函数相应介绍
occ:请参考find ()函数相应介绍
DATA: text TYPE c LENGTH 120 VALUE `Cathy's cat with the hat sat on Matt's mat.`,
regx TYPE c LENGTH 120 VALUE `\<.at\>`."\< Start of a word \> End of a word
DATA: result TYPE i,
substr TYPE string.
WRITE / text.
NEW-LINE.
result = count( val = text regex = regx ).
DO result TIMES.
result = find( val = text regex = regx occ = sy-index ).
substr = match( val = text regex = regx occ = sy-index ).
result = result + 1.
WRITE AT result substr.
ENDDO.
Cathy's cat with the hat sat on Matt's mat.
cat hat sat mat
condense去除多余空格
CONDENSE<c> [NO-GAPS].
去除字段<c>中的前导空格(注,因为是C类型,而不是String类型,所以当C类型变量末尾有空格时,去不去空格都一样,假设去掉了还会补上空格,因为C类型变量是固定宽度;但如果这里是String类型变量,则还会去除尾部空格),字符串中间的多个连续的空格使用一个空格替换。结果是左对齐单词,每个单词只用一个空格隔开。如果指定附加 NO-GAPS,则字符串中间的所有空格都也都会去除。
DATA: string TYPE string VALUE ' one two three four',
len TYPE i.
len = STRLEN( string ).
WRITE: / string, '!'.
WRITE: / 'Length: ', len.
CONDENSE string.
len = STRLEN( string ).
WRITE: / string, '!'.
WRITE: / 'Length: ', len.
CONDENSE string NO-GAPS.
len = STRLEN( string ).
WRITE: / string, '!'.
WRITE: / 'Length: ', len.
one two three four !
Length: 25
one two three four !
Length: 18
onetwothreefour !
Length: 15
String去除尾部空格
"只有使用反引号``才能保留字符串常量尾部空格
DATA: str TYPE string VALUE ` 1 `,
len TYPE i.
len = strlen( str ).
WRITE: len.
"String类型的字符串前导与后缀空格都会去掉
CONDENSE str.
len = strlen( str ).
WRITE: len.
3 1
condense()函数
condense( [val =] text [del = del] [from = from] [to = to] )
该函数不只是去除头尾空格,还可以去除头尾指定的指定字符,或者替换字符串是中间指定的字符操作
该函数的两个作用:
l 去除val头与尾部指定的del字符,如果del为空字符(0长度串),则不会删除(注:这里的del是一个字符集,只要头尾出现在del之中的某个或全部字符,都会被删除掉,而不要求头或尾完全与del匹配)
l 将from指定的子串替换成to指定的子串,如果from为空(0长度串),则不会有字符被替换,如果to为空(0长度串),则会from子字符串将会被删除(这里的from与上面的del也是一个字符集的概念,即不是要求val中间出现与from整个串匹配时才发生替换,而是只要在val中间出现了from字符集中某个字符一次或某个字符连继多次,则会将这个字符或这个字符继续出现的串替换成一个to指定的字符串)
函数返回的值的类型为 String
del、from、to的默认值为空格。
如果del、from、to未指定时,val也可以省略。
如果del, from, to为固定类型长度的字符串,则尾部空格会被省略掉
如果del、from、to都指定为空格字符` `,则与不带NO-GAPS选项的CONDENSE语句作用是一样的
DATA: result TYPE string.
result = condense(` abc def ` ).
WRITE:/ result."abc def
result = condense( val = ` abc def ` from = `` )."form为空或不指定时不会发生替换操作
WRITE:/ result."abc def
result = condense( val = `XXabcXXX1XX2XdefXX` del = 'X1' from = 'X' to = 'W' ).
WRITE:/ result."abcW1W2Wdef
result = condense( val = `XXabcXXX1XX2XdefXX` del = 'X' from = 'X' to = '' ).
WRITE:/ result."abc12def
result = condense( val = `XXabcXXX1XX2XdefXX` del = 'X' from = 'X1' to = 'W' ).
WRITE:/ result."abcW2Wdef
result = condense( val = `XXabcXXX1XX2XdefXX` del = 'X' from = 'XX' to = 'W' ).
WRITE:/ result."abcW1W2Wdef
result = condense( val = `XXabcXXX1XX2XdefXX` del = 'X' from = 'X1X' to = 'W' ).
WRITE:/ result."abcW2Wdef
result = condense( val = ` Rock'xxx'Roller` del = `re ` from = `x` to = `n` ).
WRITE:/ result."Rock'n'Roll
insert()函数
insert( val = text sub = substring [off = off] )
将字符串sub插入到text指定的off位置之前。如果sub为空(0长度串),则返回原样的 text。返回的类型为String
DATA result TYPE string VALUE `XXXXX`.
DO strlen( result ) - 1 TIMES.
result = insert( val = result sub = ` ` off = sy-index * 2 - 1 ).
WRITE: / result.
ENDDO.
result = insert( val = result sub = `W`)."如果未指定off,则会在头插入
WRITE: / result.
X XXXX
X X XXX
X X X XX
X X X X X
WX X X X X
repeat ()函数
repeat( val = text occ = occ )
将text重复occ次后返回,返回类型为string。如果val为空(0长度)字符串或者occ为0,则返回empty string
返回10个空格:result = repeat( val = ` ` occ = 10 ).
reverse()函数
DATA: result TYPE string.
WRITE:/ sy-abcde.
result = reverse( sy-abcde ).
WRITE:/ result.
ABCDEFGHIJKLMNOPQRSTUVWXYZ
ZYXWVUTSRQPONMLKJIHGFEDCBA
concatenate连接字符串
CONCATENATE {dobj1 dobj2 ...}|{LINESOF itab}
INTO result
[IN {BYTE|CHARACTER} MODE]
[SEPARATED BY sep]
[RESPECTING BLANKS].
可以对内表行进行拼接
如果结果被result容纳,则将 SY-SUBRC 设置为0。然而,如果结果被截断(result不能容纳整个结果时),则将 SY-SUBRC设置为4。防止截断,应该定义成String类型。
字符串尾部空格处理
fixed length (c, d, n, and t or structures regarded as character-type),前导空格会保留,尾部空格都会被去掉,但这个对String类型的字符串是个例外:所有空格都会保留。
CONCATENATE函数对于c, d, n, and t类型的字符串有一个RESPECTING BLANKS选项可使用,表示尾部空格也会保留(使用``对String类型进行赋值时才会保留尾部空格,两个单引号中尾部空格不能成功赋值给String类型变量,因为使用单引号引起来的串尾部的空格的字符赋给一个变长字符串时,是不能赋值过去的,编译与运动时就会自动去掉)
DATA: c1(10) VALUE 'Sum',
c2(3) VALUE 'mer',
c3(5) VALUE 'holi ',
c4(10) VALUE 'day',
c5(30),
sep(3) VALUE ' - '.
CONCATENATE c1 c2 c3 c4 INTO c5.
WRITE c5.
CONCATENATE c1 c2 c3 c4 INTO c5 SEPARATED BY sep.
WRITE / c5.
Summerholiday
Sum - mer - holi – day
在连接字符串时,如果是固定长度类型的字符串,尾部的空格会被自动的去掉,如果是变长类型的字符串,如尾部有空格时则会保留。
DATA: str1 TYPE string VALUE ` 1 `,str2 TYPE string VALUE ' 2 ', str3 TYPE string VALUE ` 3 `,str4 TYPE string,str5(8).
CONCATENATE str1 str2 str3 INTO str4.
CONCATENATE str1 str2 str3 INTO str5.
WRITE: str4,/ str5.结果是一样的
1 2 3
1 2 3
concat_lines_of()函数
concat_lines_of( [table =] itab [sep = sep] )
将内表itab的所有行通过sep链接起来,itab需要是索引表,并且行flat结构字符类型(CNDTString)
如果没有指定sep,则会直接将所有行直接链接起来。如果sep与itab行类型为固定长字符类型,则尾部空格会被忽略
DATA: BEGIN OF itab OCCURS 0,
a,
b,
END OF itab,
result TYPE string.
APPEND 'ab' to itab.
APPEND 'cd' to itab.
result = concat_lines_of( table = itab[] sep = ` ` ).
WRITE:result.
ab cd
strlen、Xstrlen获得字符串长度
In ABAP, the trailing blanks are taken into account for source fields of type string but not for data objects of type c.
在ABAP中,String类型的尾部空格会计入字符个数中,但C类型的变量尾部空格不会计算入。
strlen:对于固定长度的字符串 C、D、T、N,会忽略尾部空格,但String类型的尾部空格不会忽略。
DATA: int TYPE i,
word1(20) VALUE '12345',
word2(20),
word3(20) VALUE ' 4 '.
int = STRLEN( word1 ). WRITE int.
int = STRLEN( word2 ). WRITE / int.
int = STRLEN( word3 ). WRITE / int.
5
0
4
DATA:
c_field(5) TYPE c VALUE '12345',"10个字节
x_field(5) TYPE x VALUE '1234567890',"5个字节
len1 TYPE i,
len2 TYPE i,
c_field_off(5) TYPE c,
x_field_off(5) TYPE x.
*Length calculate
len1 = STRLEN( c_field )."以字符为单位进行计算
len2 = XSTRLEN( x_field )."以字节为单位进行计算
*Off and leng : 2(2)
c_field_off = c_field+2(2)."取两个字符(四个字节)
x_field_off = x_field+2(2)."取两个字节
*output
WRITE:/ 'value', 30 'length'.
ULINE.
WRITE:/ c_field, 30 len1.
WRITE:/ x_field, 30 len2.
SKIP 1.
ULINE.
WRITE:/ 'old value', 30 'field+2(2)'.
ULINE.
WRITE:/ c_field, 30 c_field_off.
WRITE:/ x_field, 30 x_field_off.
value length
12345 5
1234567890 5
old value field+2(2)
12345 34
1234567890 5678000000
substring()函数regex
substring( val = text [off = off] [len = len] )
offset off(从零开始)与len至少输入一个
substring_from( val = text {sub = substring}|{regex = regex} [case = case] [occ = occ] [len = len] )
截取从找到的substring或者regex子串的offset位置到offset+len位置的子串(所以最后的结果是包括了substring或者regex子串),如果substring没有找到,则会返回empty String
case:是否大小写敏感。省略时默认是大小写敏感的。'X'表示区别大小写,' '表示不区别大小写
len:表示要截取的substring个数。如果len没有指定,则会截取到text的末尾
occ:表示找第几次与substring或者regex匹配的位置。如果为正,则从头往后开始计算,如果为负,则从尾部向前计算,比如为1、2时,分别表示只找从左往右数第1次或第2次找到的位置,如果为-1、-2时,则分别表示只找从右往左数第1次或第2次找到的位置。省略时默认只取最左边第一个找到的位置。
substring_after( val = text {sub = substring}|{regex = regex} [case = case] [occ = occ] [len = len] )
与substring_from一样,只不过是从找到的substring或regex串的后面位置开始(最后的结果不包括substring或者regex子串),向后取len个字符的子串
substring_before( val = text {sub = substring}|{regex = regex} [case = case] [occ = occ] [len = len] )
与substring_from一样,只不过是从找到的substring或regex串的最前面位置开始(最后的结果不包括substring或者regex子串),向前取len个字符的子串。如果没有指定len,则取到text开头为止
substring_to( val = text {sub = substring}|{regex = regex} [case = case] [occ = occ] [len = len] )
与substring_from相同,只不过是取substring或者regex子串的前面len个,并包括substring或者regex子串
DATA result TYPE string.
result = substring( val = 'ABCDEFGH' off = 0 len = 2 ).
WRITE:/ result.
result = substring_from( val = 'ABCDEFGH' sub = 'CD' ).
WRITE:/ result.
result = substring_after( val = 'ABCDEFGH' sub = 'CD' ).
WRITE:/ result.
result = substring_before( val = 'ABCDEFGH' sub = 'CD' ).
WRITE:/ result.
result = substring_to( val = 'ABCDEFGH' sub = 'CD' ).
WRITE:/ result.
result = substring_from( val = 'ABCDEFCDGH' sub = 'CD' occ = 2 ).
WRITE:/ result.
AB
CDEFGH
EFGH
AB
ABCD
CDGH
cmax()、cmin()函数
cmax|cmin( val1 = text1val2 = text2 [val3 = text3] ... [val9 = text9] )
取val1……val9之间最大或最小的子符串。val1、val2 必需有。最多支持9个
DATA: txt TYPE string,
max TYPE string,
min TYPE string,
msg TYPE string.
txt = `one two three four five six seven eight nine ten`.
max = | |.
min = |§|.
DO.
TRY.
max = cmax( val1 = max"找最大的
val2 = segment( val = txt
index = sy-index sep = ` ` ) ).
min = cmin( val1 = min"找最小的
val2 = segment( val = txt
index = sy-index sep = ` ` ) ).
CATCH cx_sy_strg_par_val.
EXIT.
ENDTRY.
ENDDO.
msg = |Maximum is { max } and minimum is { min }|.
WRITE:/ msg.
Maximum is two and minimum is eight
translate转换大/小写、单个字符替换
TRANSLATE <c> TO UPPER CASE.
TRANSLATE <c> TO LOWER CASE.
TRANSLATE <c> USING <r>.该语句根据字段<r>中存储的替换规则替换字段<c>的所有字符。<r>包含成对字母,其中每对的第一个字母用第二个字母替换。
DATA: t(11) VALUE 'AbCdEfGhIjA',
string LIKE t,
rule(20) VALUE 'AxbXCydYEzfZ'.
string = t.
WRITE string.
TRANSLATE string TO UPPER CASE.
WRITE / string.
string = t.
TRANSLATE string TO LOWER CASE.
WRITE / string.
string = t.
TRANSLATE string USING rule.
WRITE / string.
AbCdEfGhIjA
ABCDEFGHIJA
abcdefghija
xXyYzZGhIjx
to_upper,to_lower()函数
to_upper( [val =] text )
将所有字母变大写
to_lower( [val =] text )
将所有字母变小写
overlay覆盖对应位置上的字符
OVERLAY <c1> WITH <c2> [ONLY <str>].
该语句用<c2>中的字母覆盖<c1>中相应位置上的字母,如果指定了<str>,则只覆盖在<str>中出现过的字母,如果省略 ONLY <str>,则<c1>中所有空格字符将被<c2>中对应位置上的字母所替换。
只要有一个字母被覆盖,SY-SUBRC 为 0。对于所有其它情况,将SY-SUBRC 设置为 4。如果<c1>比<c2>长,则只覆盖<c2>中的长度。
注:这不是替换字符串,它是将<c2>与<c1>对应位置(<c2>中的第1个字符被<c1>中的第1字符所覆盖)上的字符进行一个个覆盖。
DATA: t(10) VALUE 'a c e g i ',
string LIKE t,
over(10) VALUE 'ABCDEFGHIJ',
str(2) VALUE 'ai'.
string = t.
WRITE string.
WRITE / over.
OVERLAY string WITH over.
WRITE / string.
string = t.
OVERLAY string WITH over ONLY str.
WRITE / string.
a c e g i
ABCDEFGHIJ
aBcDeFgHiJ
A c e g I