匹配其他标签的正则表达式(字符串对)
regex to match othermost tags (string pair)
我有一本书是用 Sweave 写的,其中包含很多我正在尝试转换为 Rmarkdown 的 Latex。我设法编写了一个脚本,将大部分 Latex 转换为合理的降价,但嵌套列表让我望而却步。
到目前为止,我的想法是检测列表何时开始和结束,然后将其传递给 pandoc 进行转换,因为我认为制作解析器会使它变得不必要的困难。
问题是在嵌套列表时检测列表的开始和结束位置。
我在这里找到了一个匹配方括号标签的例子,但我一直无法弄清楚如何将它转换为匹配 \begin 和 \end。 ()
示例数据:
meh meh
\begin{itemize}
\item something1
\begin{itemize}
\item something1.1
\item something1.2
\end{itemize}
\item something2
\begin{itemize}
\item something2.1
\item something2.2
\end{itemize}
\end{itemize}
blah blah
\begin{itemize}
\item somethingelse1
\item somethingelse2
\end{itemize}
the end.
上面应该有两场比赛。一个用于嵌套列表,一个用于下面的列表。
这可以用正则表达式来完成吗?还是您看到了一些更聪明的方法?
在\begin{...}
和\end{...}
之间递归匹配的正则表达式是PCRE正则表达式,如
(?s)\begin\{[^{}]*}(?:(?!\(?:end|begin)).|(?R))*\end\{[^{}]*}
一个更高效的正则表达式版本(展开后,我还在前瞻中的 \begin
和 \end
之后添加了对 {
的检查)是:
\begin\{[^{}]*}(?:[^\]*(?:\(?!(?:end|begin)\{)[^\]*)*|(?R))*\end\{[^{}]*}
参见regex demo #1 and regex demo #2。 详情:
(?s)
- singleline/dotall/s
修饰符使 .
跨行匹配
\begin\{
- \begin{
字符串
[^{}]*
- {
和 }
以外的零个或多个字符
}
- 一个 }
字符
(?:(?!\(?:end|begin)).|(?R))*
- 尽可能多地出现零次或多次
(?!\(?:end|begin)).
- 任何不以 \end
或 \begin
字符序列开头的字符
|
- 或
(?R)
- 整个正则表达式模式是递归的
\end\{
- \end{
字符串
[^{}]*}
- {
和 }
以外的零个或多个字符,然后是 }
个字符。
示例 R 代码:
x <- "meh meh\n\begin{itemize}\n\item something1\n\begin{itemize}\n\item something1.1\n\item something1.2\n\end{itemize}\n\item something2\n\begin{itemize}\n\item something2.1\n\item something2.2\n\end{itemize}\n\end{itemize}\nblah blah\n\begin{itemize}\n\item somethingelse1\n\item somethingelse2\n\end{itemize}\nthe end.\n"
reg <- "(?s)\\begin\{[^{}]*}(?:(?!\\(?:end|begin)).|(?R))*\\end\{[^{}]*}"
## reg2 <- "\\begin\{[^{}]*}(?:[^\\]*(?:\\(?!(?:end|begin)\{)[^\\]*)*|(?R))*\\end\{[^{}]*}"
result <- regmatches(x, gregexpr(reg, x, perl=TRUE))
输出:
> result
[[1]]
[1] "\begin{itemize}\n\item something1\n\begin{itemize}\n\item something1.1\n\item something1.2\n\end{itemize}\n\item something2\n\begin{itemize}\n\item something2.1\n\item something2.2\n\end{itemize}\n\end{itemize}"
[2] "\begin{itemize}\n\item somethingelse1\n\item somethingelse2\n\end{itemize}"
我有一本书是用 Sweave 写的,其中包含很多我正在尝试转换为 Rmarkdown 的 Latex。我设法编写了一个脚本,将大部分 Latex 转换为合理的降价,但嵌套列表让我望而却步。
到目前为止,我的想法是检测列表何时开始和结束,然后将其传递给 pandoc 进行转换,因为我认为制作解析器会使它变得不必要的困难。 问题是在嵌套列表时检测列表的开始和结束位置。
我在这里找到了一个匹配方括号标签的例子,但我一直无法弄清楚如何将它转换为匹配 \begin 和 \end。 (
示例数据:
meh meh
\begin{itemize}
\item something1
\begin{itemize}
\item something1.1
\item something1.2
\end{itemize}
\item something2
\begin{itemize}
\item something2.1
\item something2.2
\end{itemize}
\end{itemize}
blah blah
\begin{itemize}
\item somethingelse1
\item somethingelse2
\end{itemize}
the end.
上面应该有两场比赛。一个用于嵌套列表,一个用于下面的列表。 这可以用正则表达式来完成吗?还是您看到了一些更聪明的方法?
在\begin{...}
和\end{...}
之间递归匹配的正则表达式是PCRE正则表达式,如
(?s)\begin\{[^{}]*}(?:(?!\(?:end|begin)).|(?R))*\end\{[^{}]*}
一个更高效的正则表达式版本(展开后,我还在前瞻中的 \begin
和 \end
之后添加了对 {
的检查)是:
\begin\{[^{}]*}(?:[^\]*(?:\(?!(?:end|begin)\{)[^\]*)*|(?R))*\end\{[^{}]*}
参见regex demo #1 and regex demo #2。 详情:
(?s)
- singleline/dotall/s
修饰符使.
跨行匹配\begin\{
-\begin{
字符串[^{}]*
-{
和}
以外的零个或多个字符
}
- 一个}
字符(?:(?!\(?:end|begin)).|(?R))*
- 尽可能多地出现零次或多次(?!\(?:end|begin)).
- 任何不以\end
或\begin
字符序列开头的字符|
- 或(?R)
- 整个正则表达式模式是递归的
\end\{
-\end{
字符串[^{}]*}
-{
和}
以外的零个或多个字符,然后是}
个字符。
示例 R 代码:
x <- "meh meh\n\begin{itemize}\n\item something1\n\begin{itemize}\n\item something1.1\n\item something1.2\n\end{itemize}\n\item something2\n\begin{itemize}\n\item something2.1\n\item something2.2\n\end{itemize}\n\end{itemize}\nblah blah\n\begin{itemize}\n\item somethingelse1\n\item somethingelse2\n\end{itemize}\nthe end.\n"
reg <- "(?s)\\begin\{[^{}]*}(?:(?!\\(?:end|begin)).|(?R))*\\end\{[^{}]*}"
## reg2 <- "\\begin\{[^{}]*}(?:[^\\]*(?:\\(?!(?:end|begin)\{)[^\\]*)*|(?R))*\\end\{[^{}]*}"
result <- regmatches(x, gregexpr(reg, x, perl=TRUE))
输出:
> result
[[1]]
[1] "\begin{itemize}\n\item something1\n\begin{itemize}\n\item something1.1\n\item something1.2\n\end{itemize}\n\item something2\n\begin{itemize}\n\item something2.1\n\item something2.2\n\end{itemize}\n\end{itemize}"
[2] "\begin{itemize}\n\item somethingelse1\n\item somethingelse2\n\end{itemize}"