关于bash:如何用sed将配对的方括号替换为其他语法?

How to replace paired square brackets with other syntax with sed?

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

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

这变成:

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

如何用此代码替换成对的括号?


花了点功夫,但是在这里:

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

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

  • \\[与方括号匹配。由于[是有效的魔术正则表达式字符,因此反斜杠表示匹配文字字符。
  • \\(...\\)是捕获组。它捕获了我想要的正则表达式的一部分。我可以有许多捕获组,在sed中,我可以将它们引用为\\1\\2等。
  • 在捕获组\\(...\\)中。我有[^]]*

  • [^...]语法表示任何字符,但是。
  • [^]]表示除大括号外的任何字符。
  • *表示前面的零个或多个。这意味着我正在捕获不闭合方括号的零个或多个字符。
  • \\]表示右方括号
  • 让我们看看这行是[一些]更多的[文本]

    • 在上面的#1中,我捕获了some单词前面的第一个空心方括号。但是,它不在捕获组中。这是我要替换的第一个字符。
    • 我现在开始一个捕获小组。我正在按照上面的3.2和3.3进行捕获,首先以字母s开头,并使用尽可能多的不包含方括号的字符。这意味着我正在匹配[some,但仅捕获了some
    • 在#4中,我结束了我的捕获小组。我已经出于替换目的匹配了[some,现在我在最后一个结束方括号中进行了匹配。这意味着我正在匹配[some]。注意,正则表达式通常是贪婪的。我将在下面解释为什么这很重要。
    • 现在,我可以匹配替换字符串了。这要容易得多。是\\\\macro(\\1)\\1替换为我的捕获组。 \\\\只是一个反斜杠。因此,我将[some]替换为\\macro{some}

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

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

    捕获小组现在说出方括号之间的任何内容。但是,问题在于正则表达式是贪婪的,这意味着我应该从some中的s一直匹配到文本中的最终t。下面的" x"显示捕获组。 []显示我匹配的方括号:

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

    这变得更加复杂,因为我必须匹配对正则表达式具有特殊含义的字符,因此我们看到了很多反斜杠。另外,我不得不考虑正则表达式的贪婪性,它具有漂亮的,不匹配的字符串[^]]*,可以匹配任何不包含右括号的内容。在\\[[^]]*\\]之前和之后加上方括号,不要忘记\\(...\\)捕获组:\\[\\([^]]*\\)\\],您会发现正则表达式有很多麻烦。


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

    这将查找一个左括号,任意数量的显式非右括号,然后是一个右括号。该组由括号捕获,并插入到替换表达式中。


    使用组

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

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

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

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