ABAP字符串处理函数、正则表达式

目录导航

声明:原创作品,转载时请注明文章来自SAP师太博客,并以超链接形式标明文章原始出处,否则将追究法律责任!
原文出自:

字符串处理是每门应用语言里都要掌握的,在SAP ABAP语言里也不例外,说到字符串处理,必然少不了正则式的出现,有了正则式,字符串才可以灵活处理,不过我在ABAP项目中看到的还都是使用的以前R3中老式的字符串处理语句。这节的内容是非常重要的,学好后,多复杂的字符串处理也不在话下。如果你以前学过其他语言正则式,比如Java中的正则式,这节内容看得就很轻松了。当然,正则式不是哪门语言特有的,正则式有如数据结构一样,只是使用不同语言去实现他而已,就是我一样,以前研究过Java中的正则式,然后在JavaScript中一样,最后到ABAP中,精髓还是一样,只是语句不同而已!

1.7.           字符串处理常用函数... 7

1.7.1.        count、match结合... 7

1.7.2.        FIND …SUBMATCHES. 8

1.7.3.        FIND …RESULTS  itab. 8

1.7.4.        正则式类... 9

1.7.4.1.             matches、match. 9

1.7.4.2.             contains. 10

1.7.4.3.             find_all10

1.7.4.4.             find_next. 11

1.7.4.5.             get_length、get_offset、get_submatch. 11

1.7.4.6.             replace_all12

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类型的变量尾部空格不会计算入

substring( val = TEXT [off = off] [len = len] )

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

contains( val = TEXT REGEX = REGEX)是否包含。返回布尔值,注:只能用在if、While等条件表达式中

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

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

find( val = 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 ...比分组的数量少,则多余的分组将被忽略;且只存储第一次或最后一次匹配到的结果

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

REPLACE ALL OCCURRENCES OF REGEX regex IN  dobj WITH new

1.7.1.   count、match结合

DATA: text TYPE string VALUE `Cathy‘s cat with the hat sat on Matt‘s mat.`,
      regx TYPE string VALUE `\<.at\>`."\< 单词开头,\> 单词结尾
DATA: counts TYPE i,
      index TYPE i,
      substr TYPE string.
WRITE / text.
NEW-LINE.
counts = count( val = text regex = regx )."返回匹配次数
DO counts TIMES.
  index = find( val   = text regex = regx occ = sy-index )."返回匹配到的的起始位置索引
  substr = match( val  = text regex = regx occ = sy-index )."返回匹配到的串
  index = index + 1.
  WRITE AT index substr.
ENDDO.

1.7.2.   FIND …SUBMATCHES

DATA: moff 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`"会匹配二次,但只会返回第二次匹配到的结果,第一次匹配到的子串不会存储到s1、s2、s3中去
     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

DATA: result 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.
  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[].
  "result_tab中存储了匹配到的子串本身(与Regex整体匹配的串,存储在
  "result_tab-offset、result_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 = Regularexpression   [?reɡjul?]

cl_abap_regex与Java中的 java.util.regex.Pattern的类对应

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

1.7.4.1.            matchesmatch

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

DATA: matcher TYPE REF TO cl_abap_matcher,
      match TYPE match_result,
      match_line TYPE submatch_result.
"^$可以省略,因为matches方法本身就是完全匹配整个Regex
IF cl_abap_matcher=>matches( pattern = ‘^(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-offset, match_line-length,matcher->text+match_line-offset(match_line-length).
  ENDLOOP.
ENDIF.

DATA: matcher TYPE REF TO cl_abap_matcher,
      match TYPE match_result,
      match_line TYPE submatch_result.
"^$可以省略,因为matche方法本身就是完全匹配整个Regex
matcher = cl_abap_matcher=>create( pattern = ‘^(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-offset, match_line-length,matcher->text+match_line-offset(match_line-length).
  ENDLOOP.
ENDIF.

1.7.4.2.            contains

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

DATA: matcher TYPE REF TO cl_abap_matcher,
      match TYPE match_result,
      match_lineTYPE submatch_result.
IF cl_abap_matcher=>contains( pattern = ‘(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-offset, match_line-length,matcher->text+match_line-offset(match_line-length).
  ENDLOOP.
ENDIF.

1.7.4.3.            find_all

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

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

1.7.4.4.            find_next

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

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

1.7.4.5.            get_length、get_offset、get_submatch

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

1.7.4.6.            replace_all

DATA: matcher TYPE REF TO cl_abap_matcher,
      count TYPE i,
      repstr TYPE string.
matcher = cl_abap_matcher=>create( pattern = ‘<[^<>]*>‘ text = ‘<html>hello</html>‘ ).
count = matcher->replace_all( ``)."返回替换的次数
repstr = matcher->text. "获取被替换后的新串
WRITE: / count , repstr.

时间: 2024-08-24 10:12:26

ABAP字符串处理函数、正则表达式的相关文章

js判断字符串是否全为空(使用trim函数/正则表达式)

我们需要判断用户输入的是否全是空格,可以使用以下方法: 方法一: 使用trim() /* 使用String.trim()函数,来判断字符串是否全为空*/ function kongge1(test) { let str = test.trim(); if (str.length == 0) { console.log('字符串全是空格'); } else { console.log('输入的字符串为:' + test); } } 如果 trim() 不存在,可以在所有代码前执行下面代码 /* 给

php 字符串分割函数split

说明 array split    ( string $pattern   , string $string   [, int $limit  ] ) 本函数返回一个字符串数组,每个单元为   string 经区分大小写的正则表达式   pattern 作为边界分割出的子串.如果设定了   limit,则返回的数组最多包含   limit 个单元,而其中最后一个单元包含了   string 中剩余的所有部分.如果出错,则   split() 返回 FALSE. Example #1 split(

Ruby:字符串处理函数

字符串处理函数1.返回字符串的长度 str.length => integer 2.判断字符串中是否包含另一个串 str.include? other_str => true or false "hello".include? "lo" #=> true "hello".include? "ol" #=> false "hello".include? ?h #=> true 3

JavaScript中字符串分割函数split用法实例

这篇文章主要介绍了JavaScript中字符串分割函数split用法,实例分析了javascript中split函数操作字符串的技巧,非常具有实用价值,需要的朋友可以参考下 本文实例讲述了JavaScript中字符串分割函数split用法.分享给大家供大家参考.具体如下: 先来看下面这段代码: <script type="text/javascript"> var str="How are you doing today?" document.write

PHP字符串处理与正则表达式

字符串 1. PHP中的字符串是一种基本数据类型,PHP对unicode没有本地支持. 2. 字符串可以可以通过花括号来访问每一个字符,并且每个花括号只能存放一个字符: ? ? $str = 'abcd';? ? $str{1} = 'change it';? ? echo $str; // accd 3. 双引号中变量内插解析,在双引号中的内容会被解析为字符串, ? ? 如果遇到$符号,则会贪婪解析一个尽可能多的合法变量名,使用花括号可以将变量名括起来: ? ? 在双引号中解析数组索引或者对象

ABAP发邮件函数

步骤: 一.检查输入参数, (1)未指定文件類別代碼,(2)未指定郵件主題, (3)未指定郵件內容, (4)未指定發送人郵件地址, (5)未指定接收人郵件地址, 二.调用发送功能, (1)创建发送请求 (2)创建整理发送内容, 增加附件內容(3)添加邮件内容到发送请求 (4)設置發送人出件地址 (5)接收者邮件地址转换 (6)第六步,設置狀態屬性 (7)第七步: 正式发送并提交作业 ?如何确认是否发送成功, 1.是否可以请求发送接收回执? 2.是否可以返回成功代码? ABAP发邮件函数:  表:

PHP常用字符串操作函数实例总结(trim、nl2br、addcslashes、uudecode、md5等)

/*常用的字符串输出函数 * * echo() 输出字符串 * print() 输出一个或多个字符串 * die() 输出一条信息,并退出当前脚本 * printf() 输出格式化字符串 * sprintf() 把格式化的字符串写入到一个变量中 * */ //ucfirst //将字符串中的首字母转换为大写 $str="string"; echo ucfirst($str); echo "<hr><br/>"; //ucwords() //将

oracle正则截取字符串的函数

现在有这么一个需求, 数据库中的一个手输的'籍贯'字段,要按一定的规范截取显示在报表上,比如,如果'籍贯'的内容是:'山东省潍坊市昌乐县', 那么报表里要显示为:'山东昌乐', 如果'籍贯'是山东省潍坊市寒亭区 那么就要出来 山东潍坊,简化的基本需求就是这样,取省一级和县一级,如果县一级是个区,那就取到市一级, 没有县一级的话,是数据不规范,但是先将就着取省一级和市一级. 要实现这个目的,第一是要从数据库里把相应的字段取出来, 第二是要写一个oracle截取字符串的函数处理下'籍贯'字段. 第一

ASP.NET中常用的字符串分割函数

asp.net字符串分割函数用法 先来看个简单的实例 但是其数组长度却是25,而不是3.下面这种方法是先将“[111cn.net]”替换成一个特殊字符,比如$,在根据这个字符执行Split 例如下面我要根据[111cn.net]分割的话 代码如下 复制代码 string[] arrstr2 = str.Replace("[111cn.net]", "$").Split('$'); 好了看其它方法最简单最常用的方法,以一个指定的字符进行的分割 打开vs.net新建一个