在 TeX 文件中,我有以下命令\q{aaa}{blablabla}
,并且我想隔离参数blablabla
。我已经用 sed 弄清楚了:
sed 's/\q{([^}\{])}{([^}\{])}/\2/g'
而且效果很好。
问题是当有嵌套的模式中的大括号 我想保留内部大括号。换句话说,如果
\q{aaa}{blablabla \label{BBB}}
期望的输出是
blablabla \label{BBB}
例如,我们可以想象我想保留的连续几个 LaTeX 命令
\q{aaa}{blablabla \label{BBB} blablabla \includegraphics{ccc.eps} blablabla \cite{somebody_year} blablabla
\begin{itemize}
\item AAA
\item BBB
\end{itemize}
blablabla to conclude}
这种极端 MWE 的期望输出为
blablabla \label{BBB} blablabla \includegraphics{ccc.eps} blablabla \cite{somebody_year} blablabla
\begin{itemize}
\item AAA
\item BBB
\end{itemize}
blablabla to conclude
这样的例子是一个非常(也许太)复杂的例子,因为我搜索的最终目标是优化手稿的修订(在审阅过程中)。
不确定是否可以在一行中完成sed
...
答案1
普通的正则表达式无法做到这一点;需要平衡括号的语言不是常规语言正式意义上的。因此,您无法使用 正确执行此操作sed
。幸运的是,像 Perl 这样的东西提供的正则表达式实际上不仅限于常规语言。
例如,这种令人厌恶的行为(改编自对SO的回答匹配平衡括号的正则表达式)似乎符合你想要的:
perl -0 -lne 'print "$2\n\n" while m/ \\q\{aaa\} ( \{ ( (?: [^}{]+ | (?1))*+ ) \} )/gx '
输入\q{aaa}{blablabla \label{BBB}} \foo{bar}{not this} \q{aaa}{bleh}
给出输出
blablabla \label{BBB}
bleh
即匹配的部分之间打印有两个换行符。如上所述-0
,它也应该适用于多行标签。您还可以更改print $2
为print $&
以获得完整\q{aaa}{...}
标签。
这基本上所做的是,开头\\q\{aaa\}
匹配标签的常量部分,内部部分(?: [^}{]+ | (?1))*+
匹配任意数量的东西,这些东西要么是不带大括号的字符串,要么是可以通过在第一个捕获组处递归来匹配的东西(设置括号),即里面有东西的匹配的大括号对。
.../ \\q\{aaa\} ( \{ ( (?: [^}{]+ | (?1))*+ ) \} )/ '
^1 ^2 | ^2 ^1
| | |
+---------------------+----------+
recurse to group 1
第二个捕获组用于捕获输出的部分。