用sed选择线条

时间:2010-11-13 20:23:08

标签: regex replace

我正在尝试匹配用sed替换多行块,我无法弄清楚..

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.', # Add 'postgresql_psycopg2', 'postgresql',     'mysql', 'sqlite3' or 'oracle'.
        'NAME': 'testblah',                      # Or path to database file if using     sqlite3.
        'USER': '',                      # Not used with sqlite3.
        'PASSWORD': '',                  # Not used with sqlite3.
        'HOST': '',                      # Set to empty string for localhost. Not used     with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used     with sqlite3.
    }
}

我认为最简单的方法就是这样;

sed -i "s/^DATABASES\s?+=\s?+{$+8/test/" settings.py

简而言之,我想找到DATABASES = {包含捕获中的以下8行,并将其替换为其他行。

关于什么是错的任何想法?

4 个答案:

答案 0 :(得分:2)

$ cat > f.sed
/^DATABASES/,/^}/c\ 
\
A block of replacement\
...text.
$ sed -f f.sed test.txt

更新:一般来说,应该将SO答案视为采取的方向,而不是完成食谱。正如Brian指出的那样,正则表达式中的细节将影响答案的一般性和具体程度。您可能希望更多地提出任何一个或另一个w.r.t.任何模式类...

答案 1 :(得分:1)

正则表达式不足以准确匹配大括号对。你需要一个无上下文语法。这是最接近原始问题的问题,sed可以做到:

将以DATABASES开头的行替换为test

后面的9行
sed -n -e '/^DATABASES/i test' -e '/^DATABASES/{n;n;n;n;n;n;n;n;n;n;};p' settings.py

答案 2 :(得分:1)

如果您没有被迫使用sed,那么grep -A 8'你的正则表达式'可能会起作用。 (GNU grep)

答案 3 :(得分:1)

这可能在perl中比在sed中更容易解决。首先,做多线比赛是微不足道的。

perl -0777 -pe 's/foo.*?bar/glarch/sg'

但另一方面,你实际上可以使用嵌套括号进行递归匹配,我担心你可能需要它。

此外,由于perl使用ERE并且sed使用BRE,因此您将不再需要这么多反斜杠,因此您可以更轻松地使用它。

此外,支持所有\s+类型的内容。

另外,如果这是UTF-8文本,你仍然可以;只需添加-CSD类型的命令行标志。

另外,有一个名为s2p的sed-to-perl翻译器,所以你知道它是一个合适的超集。

天哪,确实很多也是。 ☺