如何用sed替换其他语法的成对方括号?

时间:2012-05-18 03:40:53

标签: bash sed

我想用[some text]替换文件中的所有方括号对,例如\macro{some text},例如:

This is some [text].
This [line] has [some more] text.

这变为:

This is some \macro{text}.
This \macro{line} has \macro{some more} text.
  • 这些对只出现在单独的行上,从不跨越多行。
  • 有时一条线上可能有多对,但它们从不嵌套。
  • 如果在一条线上单独找到一个括号,没有一对,则不应更改它。

如何使用此代码替换这些括号对?

4 个答案:

答案 0 :(得分:25)

花了一点时间,但在这里:

sed -i.bkup  's/\[\([^]]*\)\]/\\macro{\1}/g' test.txt

让我们看看我是否可以解释这个正则表达式:

  1. \[匹配方括号。由于[是有效的魔术正则表达式字符,因此反斜杠表示匹配文字字符。
  2. (...)是一个捕获组。它捕获了我想要的正则表达式的一部分。我可以拥有多个捕获组,在sed我可以将其引用为\1\2等。
  3. 在捕获组\(...\)内。我有[^]]*
    1. [^...]语法表示任何字符,但<。li>
    2. [^]]表示任何字符,但是右括号。
    3. *表示前面的零个或多个。这意味着我正在捕获零个或多个不关闭方括号的字符。
  4. \]表示结束方括号
  5. 让我们看一下这一行是[更多] [文字]

    • 在上面的#1中,我捕捉了 some 这个词前面的第一个空方括号。但是,它不在捕获组中。这是我要替换的第一个角色。
    • 我现在开始一个捕获组。我正在根据上面的3.2和3.3捕获,从 some 中的字母s开始,尽可能多的字符不关闭方括号。这意味着我匹配[some,但只捕获some
    • 在#4中,我结束了我的捕获组。我已经匹配替换目的[some,现在我匹配最后一个结束方括号。这意味着我匹配[some]。请注意,正则表达式通常是贪婪的。我将在下面解释为什么这很重要。
    • 现在,我可以匹配替换字符串。这更容易。它是\\macro(\1)\1已被我的捕获组取代。 \\只是反斜杠。因此,我会将[some]替换为\macro{some}

    如果可以保证每行中有一组方括号,那将会容易得多。然后我就可以做到这一点:

    sed -i.bkup 's/\[\(.*\)\]/\\macro(\1)/g'
    

    捕获组现在在方括号之间说任何东西。但是,问题是正则表达式是贪婪的,这意味着我将从s中的some一直到文本中的最终t进行匹配。下面的“x”表示捕获组。 []显示我匹配的方括号:

     this is [some] more [text]
             [xxxxxxxxxxxxxxxx]
    

    这变得更加复杂,因为我必须匹配对正则表达式有特殊意义的字符,所以我们看到很多反斜杠。另外,我不得不考虑正则表达式的贪婪,这使得外观漂亮,不匹配的字符串[^]]*可以匹配任何不是结束括号的内容。在\[[^]]*\]之前和之后添加方括号,并且不要忘记\(...\)捕获组:\[\([^]]*\)\]并且你得到一个正则表达式的大混乱。

答案 1 :(得分:10)

sed -e 's/\[\([^]]*\)\]/\\macro{\1}/g' file.txt

这会查找左括号,任意数量的明确非关闭括号,然后是右括号。该组被parens捕获并插入替换表达式。

答案 2 :(得分:4)

使用群组

sed 's|\[\([^]]*\)\]|\\macro{\1}|g' file

答案 3 :(得分:2)

以下表达式与模式[a-z, A-Z and space]匹配,并将其替换为\macro{<whatever was between the []>}

sed -e 's/\[\([a-zA-Z ]*\)\]/\\macro{\1}/g'

在表达式中,\( ... \)形成一个匹配组,可以在替换中稍后引用\1