Bash 仅当字符出现在括号之间时才进行转义

Bash 仅当字符出现在括号之间时才进行转义,bash,sed,replace,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} &

我在互联网上搜索过,尝试过许多组合,但我似乎无法实现这一点

我正在尝试编写一个脚本来创建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

任何帮助都将不胜感激。

下面的代码适合我

sed 's/{\([^}]*\)&\([^}]*\)}/{\1\\\&\2}/g' input.txt > output.txt
说明:
sed
命令的
/g
标志在整行执行替换。在没有
/g
标志的情况下,
sed
仅对每行执行第一次替换

sed
命令的“搜索”字段中,我从
{
开始,查找所有不是
}
的字符,并在
&
处停止。然后,我再次查找所有不是
}
的字符,直到遇到第一个
}。此受限搜索确保我找到的
&
严格位于最近的
{
}
范围内。然后我用转义的
&`替换相同的


注意:这将仅替换给定一对花括号内的一个
&
。如果有多个
&
,则需要修改正则表达式

如果
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
    仅在匹配文本上将所有
    &
    替换为
    \&

使用在GNU sed上测试的
sed
,其他实现的语法可能会有所不同

$ echo '{1 & 7 & 0 & 2} & {Topic 2 & 3}' | sed -E ':a s/(\{[^}]*[^\\])&([^}]*\})/\1\\\&\2/; ta'
{1 \& 7 \& 0 \& 2} & {Topic 2 \& 3}
  • :标签
  • \{[^}]*[^\]
    匹配
    {
    后接零个或多个
    }
    字符和一个非
    \
    字符
  • &
    匹配
    &
    但如果前面有
    \
    礼貌
    [^\\]
  • [^}]*\}
    剩余的字符,我想可以跳过
  • \1\\\\&\2
    \
    作为
    &
  • ta
    循环到标签
    a
    ,直到替换成功

您不需要regexp的尾部:
sed的/\({[^&}]*\)和/\1\\\\&/g文件
这是真的@EdMorton。我在regexp中添加了尾部部分,以便在输入数据中需要支持多个
&
时,它可以扩展到OP。行
sed的/{\([^}]*\)和\([^}]*\)和\([^}]*\)/{\1\\\&\2\\&\3}/g'input.txt>output.txt
。。。以此类推。如果这种情况发生,那么OP应该只使用GNU awk,您可以在while循环中调用gensub()(我相信有一些GNU使用的魔法,包括30个单个字符加上蝙蝠侠符号来执行相同的操作,但为什么您会……)。