Regex sed替换同一线路上的多对相同图案

Regex sed替换同一线路上的多对相同图案,regex,sed,Regex,Sed,我想替换包含以下内容的文件test.txt some text $\alpha$ some text $\alpha$ some text some text $\beta$ some text some text $\gamma$. some text $\delta$ $\epsilon$ some text $\epsilon$ $\mu$ some text `$a$` some text `$a$` some text some text `$b$` some text some t

我想替换包含以下内容的文件
test.txt

some text $\alpha$ some text $\alpha$ some text
some text $\beta$ some text
some text $\gamma$.
some text $\delta$
$\epsilon$ some text $\epsilon$
$\mu$

some text `$a$` some text `$a$` some text
some text `$b$` some text
some text `$c$`.
some text `$d$`
`$e$` some text `$e$`
`$f$`

$$\Alpha$$
    $$\Beta$$

`$$A$$`
    `$$B$$`

简言之,我想做替换

$..$ --> `$..$`

在一组
sed
命令中。但是,如果在文件上重新应用了命令集,则不应添加额外的(`)符号

到目前为止,我已经尝试了以下几组:

    sed -e 's/^\(\$\$.*\$\$\)/`\1`/g' -i test.txt
    sed -e 's/[^`]\(\$\$[^`].*[^\$]\$\$\)[^`]/`\1`/g' -i test.txt
    sed -e 's/^\(\$.[^\$]*\$\)/`\1`/g' -i test.txt
    sed -e 's/[^`$$]\(\$[^`].[^\$]*\$\)[^`$$]/ `\1` /g' -i test.txt

但这并不完全有效

您应该能够使用一个
sed
表达式:

# ERE
sed -E 's/([^`$]|^)(\${1,2}[^`$]+\${1,2})([^`$]|$)/\1`\2`\3/g' test.txt

# or, if you prefer BRE (but only with GNU sed)
sed 's/\([^`$]\|^\)\(\$\{1,2\}[^`$]\+\$\{1,2\}\)\([^`$]\|$\)/\1`\2`\3/g' test.txt
给你:

some text `$\alpha$` some text `$\alpha$` some text
some text `$\beta$` some text
some text `$\gamma$`.
some text `$\delta$`
`$\epsilon$` some text `$\epsilon$`
`$\mu$`

some text `$a$` some text `$a$` some text
some text `$b$` some text
some text `$c$`.
some text `$d$`
`$e$` some text `$e$`
`$f$`

`$$\Alpha$$`
    `$$\Beta$$`

`$$A$$`
    `$$B$$`
我们匹配三组:

  • 前缀:单个非反勾号或非美元或行开头
  • 肉:一两块
    $
    ,然后是内容,然后是一块/两块
    $
  • 后缀:与前缀相同,只是我们匹配行尾
然后把它们打印出来,只在中间的一组中引用反勾号。我们需要锚定这些前缀和后缀,以避免重复引用你正在经历的

<强>注< <强> >上面的POSIX BRE(基本正则表达式)使用了几个GNU扩展,即:锚定在表达式中间的起始和行结束(而不是作为模式中的第一个/最后一个字符)、交替(<代码> \ <代码>)和一个或多个重复操作符(<代码> + < /代码>)。如果需要此表达式在POSIX BRE中工作,则需要将其分解为几个(即3)子表达式,并使用

\{1,\}
而不是
\+


但是还要注意,给出的POSIX ERE(扩展正则表达式)表单应该在GNU和BSD系统上的所有现代
sed
环境中都能工作。

如果您有
perl
,那么使用lookaround regex(sed regex中不支持的)会容易得多:


perl-pe的/(?嗯..我无法重现。你能缩小它不起作用的输入范围吗?因为对于你问题中的示例,它似乎起作用。是的,它添加了(`),但“.”消失了(对于文件的第4行,带增量的那一行)输入文件中的
delta
之后没有
。它适用于后跟一个点的
伽马
。如果输入可以包含
$$foo$bar$$$
,即匹配的
$
s对之间的单个
$
。idk,如果可能的话…@EdMorton,很好的捕获,谢谢。我很好奇但这是一个有效的变量名/语法。@PinkFloyd?
# ERE
sed -E 's/([^`$]|^)(\${1,2}[^`$]+\${1,2})([^`$]|$)/\1`\2`\3/g' test.txt

# or, if you prefer BRE (but only with GNU sed)
sed 's/\([^`$]\|^\)\(\$\{1,2\}[^`$]\+\$\{1,2\}\)\([^`$]\|$\)/\1`\2`\3/g' test.txt
some text `$\alpha$` some text `$\alpha$` some text
some text `$\beta$` some text
some text `$\gamma$`.
some text `$\delta$`
`$\epsilon$` some text `$\epsilon$`
`$\mu$`

some text `$a$` some text `$a$` some text
some text `$b$` some text
some text `$c$`.
some text `$d$`
`$e$` some text `$e$`
`$f$`

`$$\Alpha$$`
    `$$\Beta$$`

`$$A$$`
    `$$B$$`
perl -pe 's/(?<!`)(\$++[^\s\$]*\$++)(?!`)/`$1`/g' file

some text `$\alpha$` some text `$\alpha$` some text
some text `$\beta$` some text
some text `$\gamma$`.
some text `$\delta$`
`$\epsilon$` some text
`$\mu$`

some text `$a$` some text `$a$` some text
some text `$b$` some text
some text `$c$`.
some text `$d$`
`$e$` some text
`$f$`

`$$\Alpha$$`
    `$$\Beta$$`

`$$A$$`
    `$$B$$`
perl -i -pe 's/(?<!`)(\$++[^\s\$]*\$++)(?!`)/`$1`/g' file
(?<!`) - Negative Lookbehind to assert previous character is not `
( - Star captured group #1
   \$++ - Match one or more $
   [^\s\$]* - Match zero or more non-whitespace non-$ characters
   \$++ - Match one or more $
) - End captured group #1
(?!`) - Negative Lookahead to assert next character is not `