與SED

2010-11-13 71 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。 ☺