仅在括号内出现时才转义字符

时间:2017-07-28 04:37:26

标签: bash sed replace

我已经在互联网上搜索并尝试了很多组合,但我似乎无法让它发挥作用。

我正在尝试编写一个创建LaTeX表代码的脚本。这一切都正常,直到我在其中一个值中有一个&符号,例如

{1702} & {12389122} & {Topic 1 Online Quiz} & {1.7} & {2} & {83.3} \\\hline 
{1702} & {12389122} & {Topic 2 & 3 Online Q...} & {1.9} & {2} & {93.3} \\\hline
{1702} & {12389122} & {Topic 4 Online Quiz} & {} & {2} & {} \\\hline
{1702} & {12389122} & {Topic 5 Online Quiz ...} & {} & {2} & {} \\\hline

我需要能够读入包含此数据的input.txt文件,然后将结果输出到output.txt文件,除了第2行中的相同数据,我需要转义&符号,例如,

{1702} & {12389122} & {Topic 1 Online Quiz} & {1.7} & {2} & {83.3} \\\hline 
{1702} & {12389122} & {Topic 2 \& 3 Online Q...} & {1.9} & {2} & {93.3} \\\hline
{1702} & {12389122} & {Topic 4 Online Quiz} & {} & {2} & {} \\\hline
{1702} & {12389122} & {Topic 5 Online Quiz ...} & {} & {2} & {} \\\hline

但只能逃避{}

之间出现的&符号

我想我可能早一点接近,但我的最后一次尝试是:

sed 's/\({[a-zA-Z0-9. _]*\)\(\&\)\([a-zA-Z0-9. _]*}.*\)/\1\\\2\3/' input.txt > output.txt

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:3)

以下代码适用于我

sed 's/{\([^}]*\)&\([^}]*\)}/{\1\\\&\2}/g' input.txt > output.txt

说明: /g命令的sed标志在整行上执行替换。如果没有/g标记,sed每行只执行第一次替换。

在'搜索' sed命令的字段,我从{开始,查找非}并停在&的所有字符。然后我再次找到所有不是}的字符,直到我遇到}'. This restricted search ensures that I find& that is strictly within closest {and} . Then I am replacing the same with escaped&`。

注意:这只会替换给定花括号中的一个&。如果您有多个&,则需要修改正则表达式。

答案 1 :(得分:0)

如果perl没问题

$ echo '{1702} & {Topic 2 & 3 Online Q}' | perl -pe 's/\{[^}]+\}/$&=~s|&|\\&|gr/ge'
{1702} & {Topic 2 \& 3 Online Q}
$ echo '{1 & 7 & 0 & 2} & {Topic 2 & 3}' | perl -pe 's/\{[^}]+\}/$&=~s|&|\\&|gr/ge'
{1 \& 7 \& 0 \& 2} & {Topic 2 \& 3}
  • \{[^}]+\}匹配{后跟非}个字符,以}结尾
    • 未处理嵌套,例如:{17 {3 & 3} & 02}将提供{17 {3 \& 3} & 02}
  • /ge替换所有匹配项并允许在替换部分中使用Perl代码
  • $&=~s|&|\\&|gr仅在匹配的文字
  • 上将所有&替换为\&


对于sed,在GNU sed上进行了测试,其他实现的语法可能会有所不同

$ echo '{1 & 7 & 0 & 2} & {Topic 2 & 3}' | sed -E ':a s/(\{[^}]*[^\\])&([^}]*\})/\1\\\&\2/; ta'
{1 \& 7 \& 0 \& 2} & {Topic 2 \& 3}
  • :a标签
  • \{[^}]*[^\\]匹配{后跟零个或多个}字符和非\字符
  • &匹配&,但如果\ [^\\] <{li} {
  • [^}]*\}剩下的字符,我想可以跳过
  • \1\\\&\2会将\添加到&
  • 前面
  • ta循环标记a,直到替换成功