使用带有子组的组的 Vala 正则表达式不断以分段错误结束
Vala regex using groups with subgroups keeps ending in a segmentationfault
真的很简单。我正在尝试使用正则表达式来识别 vcard 字符串一行中的某些 属性 值。
所以,这是代码:
int main(string[] args){
string input = "TEL;VALUE=uri;PREF=1;TYPE=\"voice,home\":tel:+1-555-555-5555;ext=5555";
string regString = "(tel:(?<phnum>.*);)*(?<pref>PREF=1;)*";
Regex regex = new Regex(regString);
MatchInfo match;
regex.match(input_end, 0, out match);
stdout.printf(match.fetch_named("phnum"));
stdout.printf(match.fetch_named(pref));
return 0;
}
我真正想做的是,当标签 phnum 出现在输入中时,它适用于字符子组(因此 * 位于组的外部)。所以当我这样做时:match.fetch_named("phnum")
返回值将是:“+1-555-555-5555”。
我只是遇到分段错误,尽管正则表达式测试器应用似乎可以很好地接受该模式。
您的正则表达式应缩短为:
tel:(?<phnum>.*);$
现在 'phnum'
组将包含 phone 个号码。
printf
首先采用格式字符串。您需要将它们更改为:
stdout.printf("%s\n", match.fetch_named("phnum"));
stdout.printf("%s\n", match.fetch_named("pref"));
如果格式字符串为空,printf
将出现段错误。
如果你不想打扰格式字符串,你可以使用FileStream.puts
,但你仍然需要一个空检查:
if (match.fetch_named("phnum")!=null)
stdout.puts(match.fetch_named("phnum"));
在想regex.match(input_end
也应该是regex.match(input
在不考虑 phone 数字的确切格式的情况下,一种可能的解决方案是匹配 character class 中允许的字符并从名为 [=12= 的组中获取值]
tel:(?<phnum>[0-9+-]+)
或者更广泛的匹配可能是使用取反字符 class [^
来匹配您不想要的内容,并从名为 phnum
[= 的组中获取值20=]
tel:(?<phnum>[^\r\n;]+)
可以做很多事情来改进 Vala 代码:
- GLib 的
Regex
绑定到 PCRE 将 return 一条错误消息,提供有关无效正则表达式的一些详细信息。在 Vala 中,可以通过将 new Regex ()
放在 try...catch
块中来读取此消息。
regex.match()
returns true
当找到匹配项时,因此将 regex.match()
包装在 if
语句中会使程序更健壮
- Vala 具有空合并运算符
??
,这是在存在空值时提供替代值的便捷方式
MatchInfo
具有 next()
方法,当与 Vala 的 do {} when ()
循环结合使用时,提供了一种安全检索多个匹配项的好方法
您使用的正则表达式需要排除终止符 ;
。因此 tel:(?<phnum>[^;|.]*);
将匹配 tel:
之后除 ;
之外的所有字符,直到达到 ;
。
这是一个将所有这些放在一起的工作示例:
int main () {
string input = "TEL;VALUE=uri;PREF=1;TYPE=\"voice,home\":tel:+1-555-555-5555;ext=5555";
string regString = "tel:(?<phnum>[^;|.]*);|PREF=(?<pref>[0-9]*);";
Regex regex;
MatchInfo match;
try {
regex = new Regex(regString);
if (regex.match(input, 0, out match)) {
do {
stdout.printf("Phone number: %s\n", match.fetch_named("phnum") ?? "None");
stdout.printf("Preference: %s\n", match.fetch_named("pref") ?? "None");
}
while (match.next());
}
}
catch (Error error) {
print (@"$(error.message)\n");
return 1;
}
return 0;
}
这输出:
Phone number:
Preference: 1
Phone number: +1-555-555-5555
Preference: None
有两场比赛。有趣的是 phone 数字的第一个匹配 returns 空字符串。这是因为它是一个有效的子模式,但没有匹配任何东西。我不清楚为什么 pref
对于第二场比赛为空。这需要对正则表达式引擎中发生的事情进行更多调查,但希望这足以让您继续学习。
真的很简单。我正在尝试使用正则表达式来识别 vcard 字符串一行中的某些 属性 值。
所以,这是代码:
int main(string[] args){
string input = "TEL;VALUE=uri;PREF=1;TYPE=\"voice,home\":tel:+1-555-555-5555;ext=5555";
string regString = "(tel:(?<phnum>.*);)*(?<pref>PREF=1;)*";
Regex regex = new Regex(regString);
MatchInfo match;
regex.match(input_end, 0, out match);
stdout.printf(match.fetch_named("phnum"));
stdout.printf(match.fetch_named(pref));
return 0;
}
我真正想做的是,当标签 phnum 出现在输入中时,它适用于字符子组(因此 * 位于组的外部)。所以当我这样做时:match.fetch_named("phnum")
返回值将是:“+1-555-555-5555”。
我只是遇到分段错误,尽管正则表达式测试器应用似乎可以很好地接受该模式。
您的正则表达式应缩短为:
tel:(?<phnum>.*);$
现在 'phnum'
组将包含 phone 个号码。
printf
首先采用格式字符串。您需要将它们更改为:
stdout.printf("%s\n", match.fetch_named("phnum"));
stdout.printf("%s\n", match.fetch_named("pref"));
如果格式字符串为空,printf
将出现段错误。
如果你不想打扰格式字符串,你可以使用FileStream.puts
,但你仍然需要一个空检查:
if (match.fetch_named("phnum")!=null)
stdout.puts(match.fetch_named("phnum"));
在想regex.match(input_end
也应该是regex.match(input
在不考虑 phone 数字的确切格式的情况下,一种可能的解决方案是匹配 character class 中允许的字符并从名为 [=12= 的组中获取值]
tel:(?<phnum>[0-9+-]+)
或者更广泛的匹配可能是使用取反字符 class [^
来匹配您不想要的内容,并从名为 phnum
[= 的组中获取值20=]
tel:(?<phnum>[^\r\n;]+)
可以做很多事情来改进 Vala 代码:
- GLib 的
Regex
绑定到 PCRE 将 return 一条错误消息,提供有关无效正则表达式的一些详细信息。在 Vala 中,可以通过将new Regex ()
放在try...catch
块中来读取此消息。 regex.match()
returnstrue
当找到匹配项时,因此将regex.match()
包装在if
语句中会使程序更健壮- Vala 具有空合并运算符
??
,这是在存在空值时提供替代值的便捷方式 MatchInfo
具有next()
方法,当与 Vala 的do {} when ()
循环结合使用时,提供了一种安全检索多个匹配项的好方法
您使用的正则表达式需要排除终止符 ;
。因此 tel:(?<phnum>[^;|.]*);
将匹配 tel:
之后除 ;
之外的所有字符,直到达到 ;
。
这是一个将所有这些放在一起的工作示例:
int main () {
string input = "TEL;VALUE=uri;PREF=1;TYPE=\"voice,home\":tel:+1-555-555-5555;ext=5555";
string regString = "tel:(?<phnum>[^;|.]*);|PREF=(?<pref>[0-9]*);";
Regex regex;
MatchInfo match;
try {
regex = new Regex(regString);
if (regex.match(input, 0, out match)) {
do {
stdout.printf("Phone number: %s\n", match.fetch_named("phnum") ?? "None");
stdout.printf("Preference: %s\n", match.fetch_named("pref") ?? "None");
}
while (match.next());
}
}
catch (Error error) {
print (@"$(error.message)\n");
return 1;
}
return 0;
}
这输出:
Phone number:
Preference: 1
Phone number: +1-555-555-5555
Preference: None
有两场比赛。有趣的是 phone 数字的第一个匹配 returns 空字符串。这是因为它是一个有效的子模式,但没有匹配任何东西。我不清楚为什么 pref
对于第二场比赛为空。这需要对正则表达式引擎中发生的事情进行更多调查,但希望这足以让您继续学习。