2012-11-06 56 views
1

我有一個像正則表達式的爲層次文本

HEADER foo bar 
garbage 
SUBHEADER foo foo bar 
other garbage 
SUBHEADER foo foo bar bar 
HEADER foo baz 
SUBHEADER foo bar foo foo 
SUBHEADER foo foo foo foo 
SOMETHING bar bar bar 
HEADER baz baz 
SUBHEADER baz bar baz foo 

一個文件,其中的大寫單詞字面發生,並希望與找到SOMETHING一起對應HEADERSUBHEADER,即

HEADER foo baz 
SUBHEADER foo foo foo foo 
SOMETHING bar bar bar 

這是相當在一個程序中微不足道,但可以正則表達式嗎?我可以想象一個使用否定斷言的解決方案,但這種解決方案非常難以理解。

回答

2

如果您在SOMETHING之前尋找最近的之前的HEADER和SUBHEADER,那麼我認爲您只需要在您的正則表達式中進行非貪婪匹配 - 假設您有一個正則匹配處理器,它將一次匹配多條線,通常排除grepsed和類似的。

例如,這樣的事情:

(^HEADER.*?$).*?(^SUBHEADER.*?$).*?(^SOMETHING.*?$) 

我也假設 '.' 不匹配換行符(如PCRE_DOTALL模式),以及 '^ '/' $' 將匹配開始/在字符串中間結束行(如PCRE_MULTILINE模式)。這些是許多正則表達式實現中的可配置選項。


編輯:我修改了你在你的評論中列出的命令,並得到它的工作。

perl -0777 -ne '/.*(^HEADER.*?\n).*(^SUBHEADER.*?\n).*?(^SOMETHING.*?\n)/ms 
    and print "$1$2$3*\n"' 

(我加了「M」標誌,並重新加入開始的行爲偏執的緣故錨,你可以帶他們,如果你想退了出去。)

的關鍵思想橫空出世在開始時放置一個貪婪的匹配模式,儘量讓正則表達式匹配器允許匹配HEADER。我曾預料過這樣一場非錨定的比賽就好像它在開始時有一個隱含的貪婪匹配,但顯然在非貪婪的運營商面前它不會那樣工作。

+0

我試過這個像'perl -0777 -ne'/(HEADER.*?\n).*?(SUBHEADER.*?\n).*?(SOMETHING.*?\n)/s和打印「$ 1 $ 2 $ 3 * \ n」'',但得到了第一個HEADER和SUBHEADER。 – maaartinus

+0

確實!我修復了它。 –

+0

我得到'HEADER foo baz'這很好,但是'SUBHEADER foo bar foo foo'不是。我看到我應該有數字foos代替! – maaartinus