# preg 正则表达式扩展库使用指南

## 一. 简介

preg 是使用 PCRE(Perl Compatible Regular Expressions) 组件创建的正则表达式扩展库， 兼容 Perl,PHP 正则语法。可在正则表达式的修正符中添加"j" 选项以启用 JavaScript 兼容语法。

> 注：标准库中的 [string.regex](../../../library-reference/string/regex.md) 使用 VBScript 正则表达式语法，string.regex 与 [preg](../../../library-reference//preg/_.md)  库支持的正则表达式语法基本相同，但 string.regex 功能更简单也更慢，不支持原子分组、命名捕获组等语法。
  
preg 扩展库的用法与 PHP 里的用法大同小异，例如 PHP 中使用正则表达式拆分字符串的代码如下：

```php
$keywords = preg_split ("/[\s,]+/is", "hypertext language,,programming");
var_dump($keywords);
```

那么在 aardio 代码里用法类似，区别是先创建正则表达式对象，代码如下：

```aardio
import preg;
import console;

var $keywords = preg("/[\s,]/is").split ( "hypertext language,,programming");
console.varDump( $keywords )
console.pause(true);
```

[preg 对象的 replace 函数](../../../library-reference/preg/_.html#:~:text=replace) 用法类似模式匹配函数 [string.replace](../../builtin/string/matching.md#replace)，
同样可以将替换对象指定为回调函数、替换表、字符串(支持反向引用捕获组)。  
  
[preg 对象的全局查找函数 gmatch ](../../../library-reference/preg/_.html#:~:text=gmatch)  用法也类似模式匹配函数 [string.gmatch](../../builtin/string/matching.md#gmatch) 。 

下面是一个完整的示例：


```aardio
import console; 
import preg;

var regex = preg("(\w+\:\/\/)(?P<host>[\w.]+)");

var testString = /*
http://www.aardio.com
http://www.example.com
*/

console.log( "测试是否匹配", regex.test(testString) );
console.log( "查找匹配位置", regex.find(testString) );
console.log( "获取匹配字符串", regex.match(testString) );

//全局匹配
for scheme,host in regex.gmatch( testString  ) { 
    console.log("发现匹配字符串", scheme,host )
}

console.log( '字符串替换结果\r\n', regex.replace( testString,"ftp://\2" ) );

console.log( '函数替换结果\r\n', regex.replace( testString
        ,function(scheme,host){
                if( host == "www.aardio.com" )
                        return "ftp://" + host; 
        }  ) );
        
//数组匹配,找出所有网址并返回数组
var urls = regex.grep( {
        "http://www.aardio.com";
        "http://www.example.com";
} );

console.varDump(urls)
regex.free(); 
 
$keywords = preg("/[\s,]/is").split ( "hypertext language,,programming");
console.varDump( $keywords );
console.pause();
```

注意：

aardio 所有字符串处理函数原生支持模式匹配，aardio 模式匹配是语法简化的正则表达式，基本语法类似正则表达式，但不支持对捕获分组使用模式运算等，添加了更多实用的功能（例如局部禁用模式匹配、元序列等功能），运行速度更快。模式匹配使用`!`实现边界断言，而正则表达式使用`\b`表示单词分界, aardio提供了更多的字符类，例如`\a`表示字母，`\u`表示大写字符，`\l`表示小写字符, `\p`表示标点符号，以及使用冒号表示中文宽字符等等。  

**aardio 模式匹配式匹配实现了正则表达式最常用的主要功能，但是运行速度却比 preg 正则表达式的速度快数十倍，比 string.regex 提供的 VBS 正则表达式快数百倍**。
  
参考：[模式匹配快速入门](../../../guide/language/pattern-matching.md)


## 二. 创建正则表达式对象： 

如下 aardio 代码用于创建 preg 正则表达式对象

```aardio
import preg;  
    
var 正则表达式对象 = preg("正则表达式","模式修正符")
```

注意 aardio 并不推荐将正则表达式放在一对斜杠内 - 这种兼容 PHP 的语法意谓需要多分析一次正则， 所以 `preg( "/正则表达式/模式修正符" ）` 改为 `preg("正则表达式","模式修正符")` 更好一些。  
 
 `\` 是正则表达式的转义符，因为 aardio 单引号内是转义字符串 -  所以你必须用 `'\\'` 表示 正则表达式中的 `"\"`, 为了避免混淆一般将正则表达式或模式匹配写在双引号中，在 aardio 中双引号包含的是原样字符串（ raw string ）。

  
## 三. 正则表达式中常用模式 
  

| `/pattern/` | 匹配结果 |
| --- | --- |
| `.` | 匹配除换行符以外的所有字符 |
| `x?` | 匹配 0 次或一次 x 字符串 |
| `x*` | 匹配 0 次或多次 x 字符串，但匹配可能的最少次数 |
| `x+` | 匹配 1 次或多次 x 字符串，但匹配可能的最少次数 |
| `.*` | 匹配 0 次或一次的任何字符 |
| `.+` | 匹配 1 次或多次的任何字符 |
| `{m}` | 匹配刚好是 m 个 的指定字符串 |
| `{m,n}` | 匹配在 m个 以上 n个 以下 的指定字符串 |
| `{m,}` | 匹配 m个 以上 的指定字符串 |
| `[]` | 匹配符合 `[]` 内的字符 |
| `[^]` | 匹配不符合 `[]` 内的字符 |
| `[0-9]` | 匹配所有数字字符 |
| `[a-z]` | 匹配所有小写字母字符 |
| `[^0-9]` | 匹配所有非数字字符 |
| `[^a-z]` | 匹配所有非小写字母字符 |
| `^` | 匹配字符开头的字符 |
| `$` | 匹配字符结尾的字符 |
| `\` | 如果要在 `pattern` 模式中找寻一个特殊字符，如 `*`，则要在这个字符前加上转义符 `\` 将特殊字符还原为字面值 |
| `\d` | 匹配一个数字的字符，和 `[0-9]` 语法一样 |
| `\d+` | 匹配多个数字字符串，和 `[0-9]+` 语法一样 |
| `\D` | 非数字，其他同 `\d` |
| `\D+` | 非数字，其他同 `\d+` |
| `\w` | 英文字母或数字的字符串，和 `[a-zA-Z0-9]` 语法一样 |
| `\w+` | 和 `[a-zA-Z0-9]+` 语法一样 |
| `\W` | 非英文字母或数字的字符串，和 `[^a-zA-Z0-9]` 语法一样 |
| `\W+` | 和 `[^a-zA-Z0-9]+` 语法一样 |
| `\s` | 空格，和 `[\n\t\r\f]` 语法一样 |
| `\s+` | 和 `[\n\t\r\f]+` 一样 |
| `\S` | 非空格，和 `[^ \n\t\r\f]` 语法一样 |
| `\S+` | 和 `[^ \n\t\r\f]+` 语法一样 |
| `\b` | 匹配以英文字母,数字为边界的字符串 |
| `\B` | 匹配不以英文字母,数值为边界的字符串 |
| a&#x7c;b&#x7c;c | 匹配符合a字符 或是b字符 或是c字符 的字符串 |
| `abc` | 匹配含有 abc 的字符串 |
| `(pattern)` | `()` 这个符号会创建『捕获分组』记住所找寻到的字符串，是一个很实用的语法。第一个 `()` 内所找到的字符串在后面可以使用 `\1` 或 `$1`引用，第二个 `()` 内匹配的结果在后面可以使用 `\2` 或 `$2` 变量进行引用，以此类推下去。 |
| `\pattern\i` | `i` 这个参数表示忽略英文大小写，也就是在匹配字符串的时候，不考虑英文的大小写问题。 |

  
## 四. 正则表达式示例

| 范例 | 说明 |
| --- | --- |
| `"/perl/"` | 找到含有 perl 的字符串 |
| `"/^perl/"` | 找到开头是 perl 的字符串 |
| `"/perl$/"` | 找到结尾是 perl 的字符串 |
| "/c&#x7c;g&#x7c;i/" | 找到含有 c 或 g 或 i 的字符串 |
| `"/cg{2,4}i/"` | 找到 c 后面跟着 2个到 4个 g ，再跟着 i 的字符串 |
| `"/cg{2,}i/"` | 找到 c 后面跟着 2个以上 g ，再跟着 i 的字符串 |
| `"/cg{2}i/"` | 找到 c 后面跟着 2个 g，再跟着 i 的字符串 |
| `"/cg*i/"` | 找到 c 后面跟着 0个或多个 g ，再跟着 i 的字符串，如同`/cg{0,1}i/` |
| `"/cg+i/"` | 找到 c 后面跟着一个以上 g，再跟着 i 的字符串，如同`/cg{1,}i/` |
| `"/cg?i/"` | 找到 c 后面跟着 0个或是 1个 g ，再跟着 i 的字符串，如同`/cg{0,1}i/` |
| `"/c.i/"` | 找到 c 后面跟着一个任意字符，再跟着 i 的字符串 |
| `"/c..i/"` | 找到 c 后面跟着二个任意字符，再跟着 i 的字符串 |
| `"/[cgi]/"` | 找到符合有这三个字符任意一个的字符串 |
| `"/[^cgi]/"` | 找到没有这三个字符中任意一个的字符串 |
| `"/\d/"` | 找寻符合数字的字符，可以使用`/\d+/`来表示一个或是多个数字组成的字符串 |
| `"/\D/"` | 找寻符合不是数字的字符，可以使用`/\D+/`来表示一个或是更多个非数字组成的字符串 |
| `"/\*/"` | 找寻符合 `*` 这个字符，因为 `*` 在常规表达式中有它的特殊意思，所以要在这个特殊符号前加上` \ ` 符号，这样才会让这个特殊字符失效 |
| `"/abc/i"` | 找寻符合 abc 的字符串而且不考虑这些字符串的大小写 |

  
## 五. 正则表达式用法说明
  
### 1. 贪婪/懒惰

所有限定匹配次数的正则量词运算符都是贪婪的。它们尽可能多地匹配更多更长的目标字符串。在正则运算符后添加 `?` 能让表达式仅匹配尽可能短的长度。修改器`U`也能惰化量词运算符。 

下面是一个简单演示：

```aardio
import console;
import preg;

var str = 'hihihi oops hi';

//使用贪婪的{n,}操作符进行匹配 
var m = preg('/((hi){2,})/').match(str); //返回值将是 'hihihi'
console.log(m)

//操作符匹配,在量词运算符后添加问号表示惰化匹配
var m = preg('/((hi){2,}?)/').match(str);//返回值将是 'hihi'
console.log(m)
console.pause()
```

### 2. 分组

#### 1） 捕获组 （Capturing Groups ）<a id="capturing" href="#capturing">&#x23;</a>

在正则表达式中可以使用括号`()` 对匹配结果进行分组，在后面可以使用 `\1` 到 `\9` 引用前面的捕获组，这称为反向引用(Back referencing)。

反向引用(Back referencing)是指在正则表达式内部引用之前捕获到的内容的方法。

在 `preg().replace() `函数的替换串中可以使用 `$1` 到 `$9` 引用前面的捕获组，另外可使用`$0`引用匹配的整个字符串。在 aardio 的这个替换函数里，`$0` 到 `$9` 也可以写为 `\1` 到 `\9`，其他语言在正则替换串里则必须使用 `$`符号，这一点要注意区别。

#### 2） 命名捕获组 (Named Capturing Groups) <a id="named-cap" href="#named-cap">&#x23;</a>


在正则表达式中可以使用`(?P<name>pattern)`格式的语法指定一个正则捕获组的名称，name 指定组名，pattern 则是正则模式。

请看下面的例子：

```aardio
import console;
import preg;

var regex = preg("/(?P<quote>""|').*?(?P=quote)/");
var m = regex.exec( ' "测试字符串" ' );

//exec返回的对象，可以使用名字直接引用命名分组
console.log("使用的引号", m.quote )
console.pause()
```

上式中，quote 就是组名，`|`是改组匹配内容的正则。后面的`(?P=quote)`是在引用组名为 quote 的捕获组。

#### 3） 非捕获组 （Non-capturing group）<a id="non-cap" href="#non-cap">&#x23;</a>

在正则表达式中可以使用`(?:pattern)`格式的语法指定一个不捕获匹配结果的分组。

非捕获组同样可以对模式进行分组，并且可以对非捕获组使用其他正则运算符。

非捕获组有更好的性能，并且非捕获组不记录匹配的内容，反向引用也会忽略非捕获组（不计数）。

aardio 模式匹配中则是使用尖括号包含的 [元序列](../../builtin/string/patterns.md#non-cap) 创建非捕获组，格式为 `<subpattern>`。

#### 4） 原子分组(Atomic Groups)

使用 `(?>subpattern)` 可以创建原子分组。

原子分组是一种特殊的非捕获组，不但不会捕获匹配结果，而且在原子组内部不会记录之前匹配的位置，也不会在后续匹配失败后回溯到之前记录的位置重新匹配。

原子组通常用于提高正则表达式的性能，以避免不必要的回溯。

回溯会尝试更多可能性并匹配到更复杂的结果，但滥用回溯会严重降低匹配性能。

在不必要回溯时使用原子分组可以优化性能。

并且在有些情况下，我们需要禁用回溯才能避免匹配到不需要的结果。

示例：  <a id="atomic-group-example" href="atomic-group-example">&#x23;</a>

```aardio
import console; 
import preg;

var regex = preg("/(endif|end if|end)(?!\s+else)/");
 
console.log( regex.match("if ... end",p) )
console.log( regex.match("if ... endif",p) )
console.log( regex.match("if ... end else",p) )
console.log( regex.match("if ... end if else",p) )
 
console.pause();
```

在上面的示例中，我们期望匹配 "endif","end if","end" 三个关键词后面都没有 "else" 的字符串。

测试上面的代码，我们意外地发现 "if ... end if else" 总是能匹配成功。这就是回溯功能带来的问题。正则表达式 `(endif|end if|end)` 遇到字符串 "end if else" 以后，首先匹配 `end if` 成功，然后发现后面有不应该出现的 `else`，于是正则表达式回溯到原来的位置匹配 `end` 成功，这时候它发现后面是`if` 而不是 `else` 于是机巧地利用`回溯陷阱`返回了我们不需要的结果。

解决方法是改用匹配成功就不会往回走的原子分组，将上面的 `(endif|end if|end)` 改为 `(?>endif|end if|end)`就可以成功。

参考：[在 aardio 模式匹配语法文档中查看相同的示例](../../builtin/string/patterns.md#atomic-group-example)

### 3. 零宽断言 <a id="assertion" href="#assertion">&#x23;</a>

断言都是零宽断言(zero-width assertion)，不消费任何字符宽度。

零宽断言主要分为两种：

1. 预测断言(lookahead assertion)：  
向字符串尾部的方向预测匹配程序即将消费的字符或字符串是否符合条件。  
预测断言又分为两种：
    - `(?=pattern)`   
    正预测断言(positive lookahead assertion)。  
    向后测试子模式 pattern 是否可匹配1次，不消费任何字符宽度。
    - `(?!pattern)`  
    反预测断言(negative lookahead assertion)。  
    向后测试模式 pattern 是否不匹配至少 1 次，不消费任何字符宽度 
2. 回顾断言(lookbehind assertion)：  
向字符串开始的方向回顾匹配程序刚刚经过的字符串是否符合条件。  
回顾断言也分为两种
    - `(?<=pattern)`  
    正回顾断言(positive lookbehind assertion)。  
    向前测试子模式 pattern 是否可匹配1次，不消费任何字符宽度。
    - `(?<!pattern)`  
    反回顾断言(negative lookbehind assertion)。  
    向前测试模式 pattern 是否不匹配至少 1 次，不消费任何字符宽度 

aardio 自带模式匹配也支持 [预测断言](../../builtin/string/patterns.md#lookahead)、[边界断言（预测与回顾双向断言）](../../builtin/string/patterns.md#boundary)语法：

- `pattern?=` 正预测断言，问号放在后面并且不需要用括号包围。
- `pattern?!` 反预测断言，问号放在后面并且不需要用括号包围。
- `!pattern` 边界断言，又向断言，等价于正则表达式 (?<!pattern)(?=pattern)

### 4. 单词边界(Word Boundaries)

`\b` 匹配单词边界，这是一个零宽匹配，不消耗字符长度

例如 `/\bend\b/` 只匹配 "end" , 不会匹配 "friend" 或 "ending"。

`\B` 的作用则完全相反，匹配不是单词边界的位置。

注意：正则表达式又或者 aardio 模式匹配通常都会用大写表示反义。


### 5. 递归(Recursion)

递归(Recursion)在正则表达式中用于匹配嵌套结构，例如括号嵌套 `(this (that))` 或 HTML 标签嵌套 `<div><div></div></div>`。我们使用 `(?R)` 来表示递归调用整个模式。

下面是一个匹配嵌套括号的例子：

```regex
\(((?>[^()]+)|(?R))*\)
```

这个表达式的解释如下：
- `\(` 和 `\)` 匹配括号的开头和结尾。
- `(?>[^()]+)` 匹配不包含括号的所有字符。
- `(?R)` 递归调用整个模式，匹配嵌套的括号。
- `*` 表示匹配前面的模式零次或多次。

这个表达式会尽可能多地匹配嵌套的括号。

另一个递归的例子是匹配嵌套的 HTML 标签：

```regex
<([\w]+)([^<]*?)>((?>[^<]+)|(?R))*<\/\1>
```

这个表达式的解释如下：
- `<([\w]+)([^<]*?)>` 匹配开始标签，并捕获标签名。
- `((?>[^<]+)|(?R))*` 匹配标签内容，要么是非标签字符，要么是递归调用整个模式匹配嵌套标签。
- `<\/\1>` 匹配结束标签，`\1` 引用之前捕获的标签名。

这个表达式综合运用了字符分组、贪婪操作符、回溯以及递归来匹配嵌套的 HTML 标签。


### 6. 回调(Callbacks)

在处理匹配结果时，有时需要对特定内容进行特别的修改。此时，正则表达式的回调函数就派上用场了。

回调函数用于 `preg().replace()` 中，实现对匹配结果的动态修改。你可以为 `preg().replace()` 指定一个函数作为参数，该函数接收匹配结果数组并返回修改后的数组，作为替换的结果。

例如，我们想将某字符串中的首字母转换为大写。

首先，使用正则表达式匹配所有需要大写的字母：

```regex
/\b\w/
```

该表达式使用了单词边界和字符类。接下来，我们需要一个回调函数：

```aardio
function upperCase(firstLetter) { 
    return string.upper(firstLetter) 
}
```

函数 `upperCase` 接收匹配结果数组，并将匹配结果的首字母转换为大写。在这个例子中，`firstLetter` 代表需要大写的字母。然后，我们利用 `preg().replace()` 函数实现回调：

```aardio
import console;
import preg;

function upperCase(c) {  
    return string.upper(c) 
}

var regex = preg("/\b\w/");
var str = regex.replace("very good", upperCase); 
console.log(str)
console.pause()
```

通过这个简单的回调函数，我们就能实现强大的字符串处理功能。

### 6. 注释 (Commenting)

注释在正则表达式中虽然不用于匹配字符串，但却是理解和维护复杂正则表达式的重要工具。随着正则表达式变得越来越复杂，理解其匹配逻辑会变得越来越困难。通过在正则表达式中添加注释，可以减少未来的困惑和误解。

要在正则表达式中添加注释，可以使用 `(?#comment)` 语法，其中 `comment` 是你的注释内容。例如：

```regex
/(?#匹配数字)\d/
```

如果你计划将代码公开，添加注释显得尤为重要，这样其他人可以更容易地理解和修改你的代码。注释同样有助于你在将来重新审视自己写的代码时快速理解其逻辑。

此外，可以使用 `"x"` 或 `"(?x)"` 修饰符来格式化正则表达式，使其更具可读性。这个修饰符会让正则引擎忽略表达式中的空格和换行符。需要匹配的空格仍然可以通过 `\s` 或 `\ `（反斜杠加空格）来表示。

以下是一个使用 `"x"` 修饰符的示例：

```aardio
import preg;
import console;

var m = preg("/
\d+   # 匹配数字
\s+   # 匹配空格
\w+   # 匹配单词
/x").match("243523 test");

console.varDump(m);
console.pause();
```

上述 aardio 代码与以下代码的功能相同：

```aardio
import preg;
import console;

var m = preg("\d+(?#匹配数字)\s+(?#匹配空格)\w+(?#匹配单词)").match("243523 test");
console.varDump(m);
console.pause();
```

请始终注意代码的可读性，确保注释清晰明了。
 

## 六. 修正符列表

下面列出了当前在 `preg` 支持库中可能使用的修正符。括号中是这些修正符的内部 PCRE 常量名。修正符中的空格和换行被忽略，其它字符会导致错误。

- `i` (`_PCRE_CASELESS`) 如果设定此修正符，模式中的字符将同时匹配大小写字母。

- `j` (`_PCRE_JAVASCRIPT_COMPAT`) 如果设定此修正符，模式中启用 JavaScript 正则表达式兼容语法。

- `m` (`_PCRE_MULTILINE`) 默认情况下，PCRE 将目标字符串作为单一的一“行”字符所组成的（即使其中包含有换行符）。行起始元字符（`^`）仅匹配字符串的起始，行结束元字符（`$`）仅匹配字符串的结束，或者最后一个字符是换行符时其前面（除非设定了 `D` 修正符）。这和 Perl 是一样的。当设定了此修正符，行起始和行结束除了匹配整个字符串开头和结束外，还分别匹配其中的换行符的之后和之前。这和 Perl 的 `/m` 修正符是等效的。如果目标字符串中没有 `\n` 字符或者模式中没有 `^` 或 `$`，则设定此修正符没有任何效果。

- `s` (`_PCRE_DOTALL`) 如果设定了此修正符，模式中的圆点元字符（`.`）匹配所有的字符，包括换行符。没有此设定的话，则不包括换行符。这和 Perl 的 `/s` 修正符是等效的。排除字符类例如 `[^a]` 总是匹配换行符的，无论是否设定了此修正符。

- `x` (`_PCRE_EXTENDED`) 如果设定了此修正符，模式中的空白字符（除了被转义的或在字符类中的）完全被忽略，在未转义的字符类之外的 `#` 以及下一个换行符之间的所有字符，包括两头，也都被忽略。这和 Perl 的 `/x` 修正符是等效的，使得可以在复杂的模式中加入注释。然而注意，这仅适用于数据字符。空白字符可能永远不会出现于模式中的特殊字符序列，例如引入条件子模式的序列 `(?(` 中间。

- `A` (`_PCRE_ANCHORED`) 如果设定了此修正符，模式被强制为“anchored”，即强制仅从目标字符串的开头开始匹配。此效果也可以通过适当的模式本身来实现（在 Perl 中实现的唯一方法）。

- `D` (`_PCRE_DOLLAR_ENDONLY`) 如果设定了此修正符，模式中的美元元字符仅匹配目标字符串的结尾。没有此选项时，如果最后一个字符是换行符的话，美元符号也会匹配此字符之前（但不会匹配任何其它换行符之前）。如果设定了 `m` 修正符则忽略此选项。Perl 中没有与其等价的修正符。

- `U` (`_PCRE_UNGREEDY`)  本修正符反转了匹配数量的值使其不是默认的重复，而变成在后面跟上 `?` 才变得重复。这和 Perl 不兼容。也可以通过在模式之中设定 `(?U)` 修正符或者在数量符之后跟一个问号（如 `.*?`）来启用此选项。

- `X` (`_PCRE_EXTRA`) 此修正符启用了一个 PCRE 中与 Perl 不兼容的额外功能。模式中的任何反斜线后面跟上一个没有特殊意义的字母导致一个错误，从而保留此组合以备将来扩充。默认情况下，和 Perl 一样，一个反斜线后面跟一个没有特殊意义的字母被当成该字母本身。当前没有其它特性受此修正符控制。

- `u` (`_PCRE_UTF8`) 此修正符指定启用 UTF-8 编码文本匹配，并且按字符计数（不启用此选项，则使用按字节计数的二进制匹配），开启此选项以后，传入的字符串参数必须使用 UTF-8 编码（aardio 默认就是使用 UTF-8 编码文本字符串）。

preg 扩展库在开启此选项( UTF-8 )以后，正则表达式即按字符计数，并可对中文字符使用匹配修饰符，示例如下：

```aardio
import preg;
import console;

var regex,err = preg("/中+文/u");
$keywords,j = regex.match (  "abc中中中文" );
console.varDump(  $keywords )
console.pause(); 
```

启用了 UTF-8 编码以后，也可以使用 Unicode 匹配全部中文，如下：

```aardio
import preg;
import console;

var regex,err = preg("/[\x{4e00}-\x{9fa5}]+/u");
$keywords,j = regex.match (  "abc中文" );
console.varDump(  $keywords )
console.pause(); 
```

如果在修正符中指定 "j"，则可以使用 Javascript 的正则语法指定 Unicode 编码，如下：

```aardio
import preg;
import console;

var regex,err = preg("/[\u4e00-\u9fa5]+/ju");  
$keywords,j = regex.match (  "abc中文" );
console.varDump(  $keywords )
console.pause();
```

如果是 UTF-8 编码的字符串, 则需要象下面这样匹配中文

```aardio
import preg;
import console;

var regex,err = preg("/([\x80-\xFF]+)/");
```

 