C POSIX 正则表达式失败
C POSIX Regular Expression failure
我正在尝试在 C 编程语言中使用 POSIX 正则表达式。
我有这些正则表达式模式:
const char *regular_expression_pattern_keyword = "^(auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)";
const char *regular_expression_pattern_identifier = "^[:word:]";
const char *regular_expression_pattern_number = "^[:digit:]*";
const char *regular_expression_pattern_punctuator = "^[:punct:]";
要检查雷鬼,我有一个功能:
char **patterns = malloc ((sizeof (char) * 256) * 4);
patterns[0] = (char *) regular_expression_pattern_keyword;
patterns[1] = (char *) regular_expression_pattern_identifier;
patterns[2] = (char *) regular_expression_pattern_number;
patterns[3] = (char *) regular_expression_pattern_punctuator;
for (int i = 0; i < 4; i++)
{
regex_t regular_expression;
int status;
status = regcomp(®ular_expression, patterns[i], 0);
if (status)
{
// FIXME: Improve error handling!
printf("Error: Failed to compile regex!\n");
exit(1);
}
status = regexec(®ular_expression, "auto", 0, NULL, 0);
if (!status)
{
printf("Regex status: Match ->%s\n", patterns[i]);
}
else if (status == REG_NOMATCH)
{
printf("Regex status: No match\n");
}
else
{
// FIXME: Improve error handling!
printf("Error: Failed to match regex!\n");
exit(1);
}
regfree(®ular_expression);
}
free (patterns);
由于我不知道的原因,此雷鬼检查将 auto
匹配为 Regex status: Match ->^[:digit:]*
。我做错了什么?
您的代码中有 未定义的行为,malloc
调用和以下赋值没有按照您的预期进行。
malloc
调用分配了 1024 (256 * 4) 个连续字节,而不是指针数组(类似于 char **
)。
你不需要在这里动态分配任何东西,只需要声明一个指针数组,比如
const char *patterns[] = {
regular_expression_pattern_keyword,
regular_expression_pattern_identifier,
regular_expression_pattern_number,
regular_expression_pattern_punctuator
};
这里有几点需要注意:
[:digit:]
和其他 POSIX 字符 classes 必须在方括号 ("character") classes 内使用(例如 [[:digit:]]
), 并不孤单。否则,它们匹配来自 class 的不同符号,即 [:digit:]
匹配 1 个符号,或者 :
,或者 d
、i
、g
,或 t
.
要对 quantifying/grouping 使用交替和未转义的 brackets/parentheses,您需要使用 REG_EXTENDED
标志和 regcomp
来使用 ERE 正则表达式语法。如果不传递此标志,您使用的是 BRE 正则表达式语法,这是相当糟糕的。
现在,为什么 ^[:digit:]*
匹配 auto
?因为您要求正则表达式引擎查找 零 个或更多字符,所以 :
、d
、i
、g
或 t
。它确实在字符串的开头找到了零个这样的字符,因此,你有一个匹配项。
^[[:digit:]]\{1,\}
match 1ab
which is not a number at all
不,模式不匹配 1ab
,它只匹配 1ab
中的 1
因为您没有指定任何 边界 或锚.
要仅匹配字符串开头的数字(=数字序列),请使用
"^[[:digit:]]+(\W|$)" (or "^[[:digit:]]+([^[:digit:][:alpha:]_]|$)"
不要忘记将 REG_EXTENDED
标志传递给 regcomp
函数。
参见 this demo。请注意,在 ERE 正则表达式语法中,您可以使用 +
来匹配 1 个或多个字符,而在 BRE(没有 REG_EXTENDED
)中,您必须使用 \{1,\}
.
我正在尝试在 C 编程语言中使用 POSIX 正则表达式。
我有这些正则表达式模式:
const char *regular_expression_pattern_keyword = "^(auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)";
const char *regular_expression_pattern_identifier = "^[:word:]";
const char *regular_expression_pattern_number = "^[:digit:]*";
const char *regular_expression_pattern_punctuator = "^[:punct:]";
要检查雷鬼,我有一个功能:
char **patterns = malloc ((sizeof (char) * 256) * 4);
patterns[0] = (char *) regular_expression_pattern_keyword;
patterns[1] = (char *) regular_expression_pattern_identifier;
patterns[2] = (char *) regular_expression_pattern_number;
patterns[3] = (char *) regular_expression_pattern_punctuator;
for (int i = 0; i < 4; i++)
{
regex_t regular_expression;
int status;
status = regcomp(®ular_expression, patterns[i], 0);
if (status)
{
// FIXME: Improve error handling!
printf("Error: Failed to compile regex!\n");
exit(1);
}
status = regexec(®ular_expression, "auto", 0, NULL, 0);
if (!status)
{
printf("Regex status: Match ->%s\n", patterns[i]);
}
else if (status == REG_NOMATCH)
{
printf("Regex status: No match\n");
}
else
{
// FIXME: Improve error handling!
printf("Error: Failed to match regex!\n");
exit(1);
}
regfree(®ular_expression);
}
free (patterns);
由于我不知道的原因,此雷鬼检查将 auto
匹配为 Regex status: Match ->^[:digit:]*
。我做错了什么?
您的代码中有 未定义的行为,malloc
调用和以下赋值没有按照您的预期进行。
malloc
调用分配了 1024 (256 * 4) 个连续字节,而不是指针数组(类似于 char **
)。
你不需要在这里动态分配任何东西,只需要声明一个指针数组,比如
const char *patterns[] = {
regular_expression_pattern_keyword,
regular_expression_pattern_identifier,
regular_expression_pattern_number,
regular_expression_pattern_punctuator
};
这里有几点需要注意:
[:digit:]
和其他 POSIX 字符 classes 必须在方括号 ("character") classes 内使用(例如[[:digit:]]
), 并不孤单。否则,它们匹配来自 class 的不同符号,即[:digit:]
匹配 1 个符号,或者:
,或者d
、i
、g
,或t
.要对 quantifying/grouping 使用交替和未转义的 brackets/parentheses,您需要使用
REG_EXTENDED
标志和regcomp
来使用 ERE 正则表达式语法。如果不传递此标志,您使用的是 BRE 正则表达式语法,这是相当糟糕的。
现在,为什么 ^[:digit:]*
匹配 auto
?因为您要求正则表达式引擎查找 零 个或更多字符,所以 :
、d
、i
、g
或 t
。它确实在字符串的开头找到了零个这样的字符,因此,你有一个匹配项。
^[[:digit:]]\{1,\}
match1ab
which is not a number at all
不,模式不匹配 1ab
,它只匹配 1ab
中的 1
因为您没有指定任何 边界 或锚.
要仅匹配字符串开头的数字(=数字序列),请使用
"^[[:digit:]]+(\W|$)" (or "^[[:digit:]]+([^[:digit:][:alpha:]_]|$)"
不要忘记将 REG_EXTENDED
标志传递给 regcomp
函数。
参见 this demo。请注意,在 ERE 正则表达式语法中,您可以使用 +
来匹配 1 个或多个字符,而在 BRE(没有 REG_EXTENDED
)中,您必须使用 \{1,\}
.