如何使用sed命令用反斜杠替换字符串模式

7

我希望对以下模式进行替换(前面的规则具有更高的优先级)

\right)   -> remain unchanged
\right )  -> remain unchanged
\right]   -> remain unchanged
\right ]  -> remain unchanged
\right}   -> remain unchanged
\right }  -> remain unchanged
\ri)      -> \right)
\ri       -> \rightarrow
\right    -> \rightarrow

换句话说,如果出现任何圆括号、方括号或花括号,我希望使用\right,其他任何字符都应该替换为\rightarrow。简而言之,我试图将许多缩写的谷歌文档公式转换为正确的LaTeX格式。我得到的结果如下所示。
sed -i 's/\\ri\([^g]\)/\\right\1/g' $tempfile1  #first step substitution
sed -i 's/\\right\([^])}>|a]\)/\\rightarrow\1/g' $tempfile1 
sed -i 's/\\right \([^])}>|a]\)/\\rightarrow \1/g' $tempfile1 

它的功能还不错,除了它没有像预期的那样将\right\更改为\rightarrow\。我的测试输入tempfile1如下:

\ri\right\right \right)\right]\right }\right )\ri \right ]\righta \al \\

它进入

\rightarrow\right\rightarrow \right)\right]\right }\right )\rightarrow \right ]\rightarrow \alpha \\

注意到右边的部分没有做正确。然后我添加了下面这行代码,认为它会明确地接手剩下的部分,但是它并没有像预期的那样工作,现在我真的很困惑...

sed -i 's/\\right\\/\\rightarrow\\/g' $tempfile1 #why this does not work

非常感谢您的提前帮助!


当然,您可以使用 sed -i -e '...pattern1...' -e '...pattern2...' -e '...pattern3...' ... 将您的三个脚本合并为一个。对于千字节大小的文件,三次操作可能没有太大影响,但对于多兆字节甚至更大的文件,一次操作和三次操作的区别可能非常大。 - Jonathan Leffler
我明白了,谢谢。对于我来说,典型的文件大小不到50K(普通的LaTeX文档),但是我有30多个模式(例如\al\beta\del\b\i\sig)需要替换,并且数量随时间增加。(感谢Google文档的公式编辑器以及他们最近所做的“改进”) - gamebm
1个回答

3
问题出现在这个表达式:
sed -i 's/\\right\([^])}>|a]\)/\\rightarrow\1/g'

应用于:

\right\right\

第一次匹配读取\right\并将其替换为\rightarrow\;问题出现在扫描恢复时,它从第二个rightr开始,而不是从反斜杠(前一个匹配的一部分)开始。

简单的技巧是重复该命令...

sed -i -e 's/\\right\([^])}>|a]\)/\\rightarrow\1/g' \
       -e 's/\\right\([^])}>|a]\)/\\rightarrow\1/g'

重新扫描会通过重新开始ab initio来处理第二个\right\序列。

非常感谢您的解释,现在我觉得我更好地理解了。在我的实际问题中,我实际上有30多个模式,所以我只需简单地重复整个脚本即可。 - gamebm
1
这可能足够好了。或者,您可以使用Perl或Python代替sed,并在模式中使用尾部上下文,以便\right\中的第二个反斜杠不是第一次匹配的一部分,并且重复在您想要的位置继续。 - Jonathan Leffler
我必须学习这些东西,我知道sed不擅长操作多行文档,因此我无法正确处理它们。例如,一旦发现一个\(双反斜杠),我需要在下一行的开头添加一个\n(换行符)和一个额外的&,如果它们还没有存在的话。(\alpha\\beta 变成 \alpha\n&\beta)这是为了正确对齐方程组。我知道perl应该很容易处理这个问题,但对于sed来说似乎太困难了。 - gamebm
我会说 sed 处理多行文档(文件)没问题;但它处理多行模式不如此简单。但是,我不确定你在工作中是否需要考虑多行模式。例如,你可能需要考虑你的代码能否处理行尾的 \r。我没有对你的模式进行审查。 - Jonathan Leffler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接