编译,步骤或高级子例程
用途
编译并匹配正则表达式模式。
库
标准 C 库 (libc.a)
语法
#define INIT declarations
#define GETC( ) getc_code
#define PEEKC( ) peekc_code
#define UNGETC(c) ungetc_code
#define RETURN(pointer) return_code
#define ERROR(val) error_code描述
/usr/include/regexp.h 文件包含执行正则表达式模式匹配的子例程。 执行正则表达式模式匹配的程序使用此源文件。 因此,仅需要更改 regexp.h 文件以保持程序之间的正则表达式兼容性。
此文件的接口很复杂。 包含此文件的程序在 #include <regexp.h> 语句之前定义以下六个宏。 这些宏由 编译 子例程使用:
| 项 | 描述 |
|---|---|
| INIT | 此宏用于从属声明和初始化。 它放在 compile 子例程的声明和打开 {(左花括号) 之后。 INIT 缓冲区的定义必须以; (分号) 结尾。 INIT 经常用于设置寄存器变量以指向正则表达式的开头,以便可以在 GETC PEEKC的声明中使用此寄存器变量。 和 UNGETC 宏。 否则,可以使用 INIT 来声明 GETC, PEEKC和 UNGETC 所需的外部变量。 |
| GETC () | 此宏返回正则表达式模式中下一个字符的值。 对 GETC 宏的连续调用应返回模式的连续字符。 |
| PEEKC () | 此宏返回正则表达式中的下一个字符。 对 PEEKC 宏的连续调用应该返回相同的字符,这也应该是 GETC 宏返回的下一个字符。 |
| UNGETC (c) | 此宏导致下一次调用 GETC 和 PEEKC 宏时返回参数 c 。 永远不需要多个回送字符,并且此字符可以保证是 GETC 宏读取的最后一个字符。 始终忽略 UNGETC 宏的返回值。 |
| RETURN (指针) | 此宏用于 编译 子例程的正常出口。 pointer 参数指向紧跟在已编译的正则表达式之后的第一个字符。 这对于具有要管理的内存分配的程序很有用。 |
| 错误 (val) | 此宏用于从 编译 子例程异常退出。 它不应包含 return 语句。 val 参数是一个错误号。 错误值及其含义为:
|
编译 子例程编译正则表达式以供以后使用。 InString 参数从不由 编译 子例程显式使用,但您可以在宏中使用该参数。 例如,可以使用 编译 子例程将包含该模式的字符串作为 InString 参数传递到 编译 ,并使用 INIT 宏来设置指向此字符串开头的指针。 示例 部分中的示例使用此方法。 如果您的宏不使用InString,则调用编译时该参数的值应为((char *) 0)。
ExpBuffer 参数指向要放置已编译正则表达式的字符数组。 EndBuffer 参数指向紧跟在要放置编译的正则表达式的字符数组后面的位置。 如果编译后的表达式无法容纳在(EndBuffer-ExpBuffer) 字节内,则会调用ERROR(50)。
EndOfFile参数是标记正则表达式结束的字符。 例如,在 ed 命令中,此字符通常为/(斜杠)。
regexp.h 文件定义执行实际正则表达式模式匹配的其他子例程。 其中之一是 step 子例程。
step 子例程的 String 参数是指向要检查是否匹配的以 null 结束的字符串的指针。
Expbuffer 参数指向通过调用 编译 子例程获得的已编译正则表达式。
step 子例程返回值 1 (如果给定的字符串与模式匹配) 和 0 (如果它不匹配)。 如果匹配,那么 step 还会设置两个全局字符指针: loc1(指向与模式匹配的第一个字符) 和 loc2。 它指向紧跟在与模式匹配的最后一个字符后面的字符。 因此,如果正则表达式与整个字符串匹配,那么 loc1 将指向 字符串 参数的第一个字符,而 loc2 将指向 字符串 参数末尾的空字符。
step 子例程使用全局变量 昼夜,如果正则表达式以 ^ (抑扬符) 开头,那么此变量由 编译 子例程设置。 如果设置了此变量,那么 step 仅尝试将正则表达式与字符串的开头相匹配。 如果在执行第一个正则表达式之前编译多个正则表达式,请保存每个已编译表达式的 昼夜 值,并在每次调用 step之前将 昼夜 设置为该保存的值。
使用传递给它的相同参数, step 子例程调用名为 advance的子例程。 step 函数通过 String 参数递增,并调用 advance 子例程,直到它返回 1 (指示匹配) 或直到到达 String 的末尾为止。 要在所有情况下将 String 参数限制为字符串开头,请直接调用 advance 子例程,而不是调用 step 子例程。
当 advance 子例程在正则表达式中迂到 * (星号) 或 \{ \} 序列时,它将其指向要尽可能匹配的字符串的指针,并以递归方式调用自身,尝试将字符串的其余部分与正则表达式的其余部分匹配。 只要没有匹配项, advance 子例程就会沿着字符串备份,直到它找到匹配项或到达字符串中最初与 * 或 \{ \}匹配的点。您可以在到达字符串中的初始点之前停止此备份。 如果 locs 全局字符在备份过程中的某个时间等于字符串中的点,那么 advance 子例程将脱离备份并返回 0 的循环。 这用于整行上的全局替换,以便表达式 (例如,s/y*//g不要永远循环
参数
| 项 | 描述 |
|---|---|
| InString | 指定包含要编译的模式的字符串。 InString 参数未由 compile 子例程显式使用,但它可以在宏中使用。 |
| ExpBuffer | 指向要放置已编译的正则表达式的字符数组。 |
| EndBuffer | 指向紧跟在要放置编译的正则表达式的字符数组后面的位置。 |
| EndOfFile | 指定用于标记正则表达式结束的字符。 |
| String | 指向要检查是否匹配的以 null 结束的字符串。 |
示例
以下是正则表达式宏和调用的示例:
#define INIT register char *sp=instring;
#define GETC() (*sp++)
#define PEEKC() (*sp)
#define UNGETC(c) (--sp)
#define RETURN(c) return;
#define ERROR(c) regerr()
#include <regexp.h>
. . .
compile (patstr,expbuf, &expbuf[ESIZE], '\0');
. . .
if (step (linebuf, expbuf))
succeed( );
. . .