TXR:如何合并下一行以制表符开头的所有行?
TXR: How to combine all lines where the following line begins with a tab?
我正在尝试使用 txr 解析 shell 命令的文本输出。
文本输出在其后使用制表符缩进行来继续当前行(不是文字 \t
字符,如下所示)。请注意,在其他变量赋值行(不代表扩展长度值)上,输入中有前导空格。
Variable Group: 1
variable = the value of the variable
long_variable = the value of the long variable
\tspans across multiple lines
really_long_variable = this variable extends
\tacross more than two lines, but it
\tis unclear how many lines it will end up extending
\tacross ahead of time
Variable Group: 2
variable = the value of the variable in group 2
long_variable = this variable might not be that long
really_long_variable = neither might this one!
我如何使用 txr 模式语言捕获这些?我知道 @(freeform)
指令,它是可选的数字参数,用于将接下来的 n
行视为一大行。因此,在我看来正确的方法应该是这样的:
@(collect)
Variable Group: @i
variable = @value
@(freeform 2)
long_variable = @long_value
@(set long_value @(regsub #/[\t ]+/ "" long_value))
@(freeform (count-next-lines-starting-with-tab))
really_long_variable = @really_long_value
@(set really_long_value @(regsub #/[\t ]+/ "" really_long_value))
@(end)
但是,我不清楚如何使用 TXR lisp 编写 count-next-lines-starting-with-tab
过程。另一方面,也许还有另一种更好的方法可以解决这个问题。您能提供一些建议吗?
提前致谢!
让我们应用 KISS 原则;我们不需要引入 @(freeform)
。相反,我们可以分别捕获(可能)multi-line 变量的主线和续线。然后,智能地将它们与 @(merge)
:
结合起来
@(collect)
Variable Group: @i
variable = @value
long_variable = @l_head
@ (collect :gap 0 :vars (l_cont))
@l_cont
@ (end)
really_long_variable = @rl_head
@ (collect :gap 0 :vars (rl_cont))
@rl_cont
@ (end)
@ (merge long_variable l_head l_cont)
@ (merge really_long_variable rl_head rl_cont)
@(end)
请注意,上面的大缩进应该是文字制表符。我们可以使用 @\t
.
编码制表符,而不是文字制表符
在真实数据上测试 运行,将 \t
替换为制表符:
$ txr -Bl new.txr data
(i "1" "2")
(value "the value of the variable" "the value of the variable in group 2")
(l_head "the value of the long variable" "this variable might not be that long")(l_cont ("spans across multiple lines") nil)
(rl_head "this variable extends" "neither might this one!")
(rl_cont ("across more than two lines, but it" "is unclear how many lines it will end up extending"
"across ahead of time") nil)
(long_variable ("the value of the long variable" "spans across multiple lines")
("this variable might not be that long"))
(really_long_variable ("this variable extends" "across more than two lines, but it"
"is unclear how many lines it will end up extending" "across ahead of time")
("neither might this one!"))
我们使用严格的 collect
和 :vars
作为后续行,这样即使没有收集到任何内容,变量也会被绑定(到 nil
)。 :gap 0
防止这些内部集合扫描不以制表符开头的行:另一个严格措施。
@(merge)
具有 "special" 语义,用于组合具有不同嵌套级别的字符串列表;它非常适合从 collection 的不同级别组装数据,并且基本上是为这种事情量身定做的。此问题与提取 HTTP、Usenet 或 e-mail headers 非常相似,它们可以有续行。
关于如何写一个Lisp函数在数据中向前看的话题,最重要的方面是如何获得当前位置数据的句柄。 TXR 模式匹配通过在惰性字符串列表 (lines/records) 上回溯来工作。我们可以使用 @(data)
指令在给定的输入位置捕获列表指针。然后我们可以将其视为一个列表:
@(data here)
@(bind tab-start-lines @(length (take-while (f^ #/\t/) here))
现在 tab-start-lines
计算了输入中有多少行以制表符开头。然而,不幸的是,take-while
有一个终止条件错误;如果以下数据仅由一行或多行 tab
组成,则行为不正常。⚠ 在 TXR 166 发布之前,这需要一些解决方法:(take-while [iff stringp (f^ #/\t/)] here)
。
我正在尝试使用 txr 解析 shell 命令的文本输出。
文本输出在其后使用制表符缩进行来继续当前行(不是文字 \t
字符,如下所示)。请注意,在其他变量赋值行(不代表扩展长度值)上,输入中有前导空格。
Variable Group: 1
variable = the value of the variable
long_variable = the value of the long variable
\tspans across multiple lines
really_long_variable = this variable extends
\tacross more than two lines, but it
\tis unclear how many lines it will end up extending
\tacross ahead of time
Variable Group: 2
variable = the value of the variable in group 2
long_variable = this variable might not be that long
really_long_variable = neither might this one!
我如何使用 txr 模式语言捕获这些?我知道 @(freeform)
指令,它是可选的数字参数,用于将接下来的 n
行视为一大行。因此,在我看来正确的方法应该是这样的:
@(collect)
Variable Group: @i
variable = @value
@(freeform 2)
long_variable = @long_value
@(set long_value @(regsub #/[\t ]+/ "" long_value))
@(freeform (count-next-lines-starting-with-tab))
really_long_variable = @really_long_value
@(set really_long_value @(regsub #/[\t ]+/ "" really_long_value))
@(end)
但是,我不清楚如何使用 TXR lisp 编写 count-next-lines-starting-with-tab
过程。另一方面,也许还有另一种更好的方法可以解决这个问题。您能提供一些建议吗?
提前致谢!
让我们应用 KISS 原则;我们不需要引入 @(freeform)
。相反,我们可以分别捕获(可能)multi-line 变量的主线和续线。然后,智能地将它们与 @(merge)
:
@(collect)
Variable Group: @i
variable = @value
long_variable = @l_head
@ (collect :gap 0 :vars (l_cont))
@l_cont
@ (end)
really_long_variable = @rl_head
@ (collect :gap 0 :vars (rl_cont))
@rl_cont
@ (end)
@ (merge long_variable l_head l_cont)
@ (merge really_long_variable rl_head rl_cont)
@(end)
请注意,上面的大缩进应该是文字制表符。我们可以使用 @\t
.
在真实数据上测试 运行,将 \t
替换为制表符:
$ txr -Bl new.txr data
(i "1" "2")
(value "the value of the variable" "the value of the variable in group 2")
(l_head "the value of the long variable" "this variable might not be that long")(l_cont ("spans across multiple lines") nil)
(rl_head "this variable extends" "neither might this one!")
(rl_cont ("across more than two lines, but it" "is unclear how many lines it will end up extending"
"across ahead of time") nil)
(long_variable ("the value of the long variable" "spans across multiple lines")
("this variable might not be that long"))
(really_long_variable ("this variable extends" "across more than two lines, but it"
"is unclear how many lines it will end up extending" "across ahead of time")
("neither might this one!"))
我们使用严格的 collect
和 :vars
作为后续行,这样即使没有收集到任何内容,变量也会被绑定(到 nil
)。 :gap 0
防止这些内部集合扫描不以制表符开头的行:另一个严格措施。
@(merge)
具有 "special" 语义,用于组合具有不同嵌套级别的字符串列表;它非常适合从 collection 的不同级别组装数据,并且基本上是为这种事情量身定做的。此问题与提取 HTTP、Usenet 或 e-mail headers 非常相似,它们可以有续行。
关于如何写一个Lisp函数在数据中向前看的话题,最重要的方面是如何获得当前位置数据的句柄。 TXR 模式匹配通过在惰性字符串列表 (lines/records) 上回溯来工作。我们可以使用 @(data)
指令在给定的输入位置捕获列表指针。然后我们可以将其视为一个列表:
@(data here)
@(bind tab-start-lines @(length (take-while (f^ #/\t/) here))
现在 tab-start-lines
计算了输入中有多少行以制表符开头。然而,不幸的是,take-while
有一个终止条件错误;如果以下数据仅由一行或多行 tab
组成,则行为不正常。⚠ 在 TXR 166 发布之前,这需要一些解决方法:(take-while [iff stringp (f^ #/\t/)] here)
。