编译,步骤或高级子例程

用途

编译并匹配正则表达式模式。

注: 命令将 regcompregexecregfreeregerror 子例程用于本文中描述的函数。

标准 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

#include <regexp.h>
#include <NLregexp.h>
char *compile (InStringExpBufferEndBufferEndOfFile)
char * ExpBuffer;
char  * InString, * EndBuffer;
int  EndOfFile;
int step (StringExpBuffer)
const char * String, *ExpBuffer;
int advance (String, ExpBuffer)
const char *String, *ExpBuffer;

描述

/usr/include/regexp.h 文件包含执行正则表达式模式匹配的子例程。 执行正则表达式模式匹配的程序使用此源文件。 因此,仅需要更改 regexp.h 文件以保持程序之间的正则表达式兼容性。

此文件的接口很复杂。 包含此文件的程序在 #include <regexp.h> 语句之前定义以下六个宏。 这些宏由 编译 子例程使用:

描述
INIT 此宏用于从属声明和初始化。 它放在 compile 子例程的声明和打开 {(左花括号) 之后。 INIT 缓冲区的定义必须以; (分号) 结尾。 INIT 经常用于设置寄存器变量以指向正则表达式的开头,以便可以在 GETC PEEKC的声明中使用此寄存器变量。 和 UNGETC 宏。 否则,可以使用 INIT 来声明 GETCPEEKCUNGETC 所需的外部变量。
GETC () 此宏返回正则表达式模式中下一个字符的值。 对 GETC 宏的连续调用应返回模式的连续字符。
PEEKC () 此宏返回正则表达式中的下一个字符。 对 PEEKC 宏的连续调用应该返回相同的字符,这也应该是 GETC 宏返回的下一个字符。
UNGETC (c) 此宏导致下一次调用 GETCPEEKC 宏时返回参数 c 。 永远不需要多个回送字符,并且此字符可以保证是 GETC 宏读取的最后一个字符。 始终忽略 UNGETC 宏的返回值。
RETURN (指针) 此宏用于 编译 子例程的正常出口。 pointer 参数指向紧跟在已编译的正则表达式之后的第一个字符。 这对于具有要管理的内存分配的程序很有用。
错误 (val) 此宏用于从 编译 子例程异常退出。 它不应包含 return 语句。 val 参数是一个错误号。 错误值及其含义为:
错误
含义
11
时间间隔端点太大
16
错误数字
25
\ 数字 超出范围
36
非法或缺少定界符
41
无已记住的搜索字符串
42
\ (? \) 不平衡
43
太多。(
44
在 \{ \} 中提供了两个以上的数字
45
} 预期在 \ 之后。
46
第一个数字超过了{ \} 中的第二个数字
49
[] 不平衡
50
正则表达式溢出
70
范围中的端点无效

编译 子例程编译正则表达式以供以后使用。 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不要永远循环

注: 在 64 位方式下,不支持这些接口: 它们失败,返回码为 0。 为了使用此功能的 64 位版本,应用程序应该迁移到 fnmatchglobregcompregexec 函数,这些函数提供与 ISO 9945-1:1996 (IEEE POSIX 1003.1) 和 UNIX98 规范兼容的完整国际化正则表达式功能。

参数

描述
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( );
 . . .