sed在捕获组中行为不正常;我看不出有什么不对

时间:2015-03-18 18:56:37

标签: regex bash sed

很抱歉不得不发布这个似乎相当基本的内容,但我无法说明为什么它不起作用:

sed -r -i.bak 's/-- Database: (.*?)\n/CREATE DATABASE \1\n/g' file.sql

该文件包含如下所示的行:

-- Database: `omptest`

与sublime中的find / replace完全相同的工作正常:

Find: -- Database: (.*?)\n
Replace with: CREATE DATABASE \1\n
除了我要么绕过捕获组周围的括号或者使用-r来扩展正则表达式,否则sed似乎不喜欢\ 1,否则它会抛出sed:-e expression#1,char 53:invalid reference \ 1关于's'命令的RHS。

无论如何,当我使用-r或转义括号时,它不会编辑文件,就好像它没有工作一样。我不明白为什么。

我想我要忘记或刚刚发现sed正则表达式的一些奇怪的属性,但我不能为我的生活找出问题所在。帮助赞赏!

1 个答案:

答案 0 :(得分:4)

sed在基于行的基础上工作,并且不会在文件中看到换行符(除非您执行特殊操作)。使用

#                                 vvv----------------vvv--- no newlines
sed -r -i.bak 's/-- Database: (.*?)/CREATE DATABASE \1/g' file.sql

附录:还有三点需要注意:

  1. .*?与sed中的.*完全相同。前者可用于其他一些正则表达式引擎中的非贪婪匹配,但不能用于sed。 ?没有任何伤害,但它根本不做任何事情。
  2. 由于正则表达式贪婪地匹配到行尾,/g标志不会产生任何影响。永远不会成为第二场比赛,因为第一场比赛延伸到了比赛结束。
  3. 由于捕获组被放回到发现的位置,因此首先不需要捕获它。
  4. 从前两个观察中,我们可能会得到原始脚本的简化版本:

    sed -r -i.bak 's/-- Database: (.*)/CREATE DATABASE \1/' file.sql
    

    ......由于第三种情况,我们可以再次抛弃这些变化,只需使用

    sed -i.bak 's/-- Database: /CREATE DATABASE /' file.sql
    

    代替。