与SED

2010-11-13 77 views
2

我想匹配替换多行与SED块,我无法弄清楚选择线..与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个以下行并替换成别的东西。

有什么不对的想法?

+0

我认为问题在于你没有引入比赛中的所有线,但它已经有一段时间了。默认情况下,sed模式一次只能在一行中运行,你必须做一些事情来使用其他命令引入下一行。 – caveman 2010-11-13 20:29:02

回答

1

正则表达式不够强大,无法准确地匹配成对的大括号。你需要一个上下文无关的语法。这里是最接近你在做什么原来的问题是问的是SED能做到:

替换开头的行DATABASES和9以下几行test

sed -n -e '/^DATABASES/i test' -e '/^DATABASES/{n;n;n;n;n;n;n;n;n;n;};p' settings.py 
+0

这正是我想要做的,谢谢! – 2010-11-14 16:31:11

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

更新:一般情况下应该寻找在SO回答作为方向采取而不是完成食谱。正如布莱恩指出的那样,正则表达式中的细节会影响答案的一般性和具体性。你可能希望对任何一个或另一个w.r.t提出更多的建议。任何模式类...

+0

这样做的问题是,它假定在DATABASE JSON字符串结束后文件中不会有任何其他'}'。例如,复制两次输入并将第二个DATABASES更改为FOO。它将取代两者。 – 2010-11-13 21:02:18

+0

我在'}'之前错过了'^'。这只有在最后一个大括号(并且只有最后一个大括号)位于该行的开头时才有效。如果文本格式正确,这很好。我将删除我的投票。 编辑:奇怪,它似乎并不想让我撤消我的投票。 – 2010-11-13 22:05:29

+0

@布莱恩,呃,别担心,我有很多要点。 Stackoverflow很幸运有像您这样的人仔细分析不断增长的数据库。 (我会编辑这个问题,但是,这将解决缩回时间锁定问题。) – DigitalRoss 2010-11-13 22:18:58

1

如果你不是被迫使用sed,grep -A 8'你的正则表达式'可能工作。 (GNU grep)

1

这在perl中比在sed中更容易解决。首先,做多行匹配是微不足道的。

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

但另一方面,你实际上可以做嵌套括号的递归匹配,我担心你可能需要在这里。

此外,由于perl使用EREs和sed使用BREs,所以您将有更轻松的时间,因为您不需要太多反斜杠。

此外,所有\s+类型的东西都支持。另外,如果这是UTF-8文本,你仍然会很好;只需添加一个-CSD类型的命令行标志。

此外,还有一个叫做s2p的sed-to-perl翻译器,所以你知道它是一个适当的超集。

天哪,那肯定很多 s。 ☺