sed在同一行

时间:2017-08-03 16:50:04

标签: 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 text `$c$`.
some text `$d$`
`$e$` some text `$e$`
`$f$`

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

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

通过

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
some text `$b$` some text
some text `$c$`. 
some text `$d$`
`$e$` some text `$e$`
`$m$`

`$$\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

但这不能完全发挥作用......

2 个答案:

答案 0 :(得分:1)

您应该可以使用单个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(扩展正则表达式)形式应该适用于所有现代sed环境,GNU和BSD系统。

答案 1 :(得分:1)

如果你有perl那么使用外观正则表达式更容易(sed正则表达式不支持):

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

RegEx Demo

RegEx分手:

(?<!`) - 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 `