LLVM 项目博客

LLVM 项目新闻和来自实战的细节

正则表达式命令

LLDB 用户们好。我想开始定期发布博客文章,介绍 LLDB 的新功能和酷炫特性。今天我就从刚刚添加的一项功能开始:正则表达式命令。





什么是正则表达式命令?它是一种智能别名,可以用来定义其他命令,使用“
command regex” 命令定义。定义正则表达式命令时,需要提供命令名称,以及一系列正则表达式和替换对。正则表达式和替换对以标准的流编辑器搜索和替换格式提供:

s/<regex>/<subst>/

当后来输入命令时,它将剥离正则表达式命令名称和任何后续空格,并将原始参数字符串传递到您的正则表达式列表中,按照输入顺序进行匹配。第一个 <regex> 匹配原始参数字符串后,将允许用 在由 <subst>.

假设我们想使用 "f" 作为命令来按帧索引选择帧。按帧索引选择帧的命令是 "frame select <num>" 命令,您可能并不总是想完整地输入它。我们可以使用正则表达式命令来简化操作:

(lldb) command regex f 's/([0-9]+)/frame select %1/'

"command regex f" 告诉解释器创建一个名为 "f" 的新正则表达式命令,当在命令行上输入以 "f" 开头的命令时,它会将剩余的命令文本与正则表达式 "([0-9]+)" 进行匹配,如果匹配成功,则会将任何带括号的子表达式进行替换。这里我们将数字正则表达式 "[0-9]+" 括起来,这将保存第一个匹配的结果,并允许将匹配的字符串替换到匹配替换文本 "frame select %1" 中。当我们从 LLDB 命令行使用新的正则表达式命令时,它会向我们展示正则表达式替换后生成的命令:

(lldb) f 12
frame select 12

任何正则表达式命令 "f" 后的前导空格都将在匹配正则表达式之前被剥离,但可能存在尾随空格,因为我们正在处理紧随初始 "f" 命令名称之后的剩余原始命令字符串。正则表达式也只查找任何一个或多个数字的序列。当前的正则表达式实际上会匹配:

(lldb) f 11 22 33
frame select 11


由于这不是我们想要的,因此我们应该使正则表达式更完整,检查行首(^)和行尾($),并允许在数字之后出现零个或多个空格([[:space:]]*)。我们更新后的更安全的正则表达式命令行如下所示:

(lldb) command regex f 's/^([0-9]+)[[:space:]]*$/frame select %1/'

现在我们可以像 "f 12 " (注意尾随空格)那样输入命令,仍然可以获得正确的替换,而我们之前的示例 "f 11 22 33" 将不再匹配:

(lldb) f 11 22 33
error: Command contents '11 22 33' failed to match any regular expression in the 'f' regex command.


让我们更进一步,也使用 f 命令来模拟 GDB 的 finish 命令,当它在没有参数的情况下被输入时。我们还将修改此命令以监控单个“+”或“ - ”后面跟着一个数字,以表示使用 frame select 命令的 --relative 选项进行相对帧更改:

(lldb) frame select --relative

可以在命令行上输入多个正则表达式,或者在实时 LLDB 调试会话中输入时使用多行模式。以下是粗体文本中用户输入的内容:

(lldb) commands regex f
以 's/
//' 形式输入正则表达式,并用空行结束:
s/^([0-9]+)[[:space:]]*$/frame select %1/
s/^([+-][0-9]+)[[:space:]]*$/frame select --relative=%1/
s/^[[:space:]]*$/finish/


(lldb)
f
finish
...
(lldb)
f -1
frame select --relative=-1
...
(lldb)
f +1
frame select --relative=+1
...
(lldb)
f 12
frame select 12

希望您能看到使用这些命令自定义 LLDB 命令行体验的可能性。您可以将任何正则表达式命令添加到您的
~/.lldbinit 文件中,以便在调试会话中始终定义您的正则表达式命令。