2015-04-29 47 views
1

我想產生一個sed腳本轉換不匹配行後多行模式單sed腳本打破

&&a_x* &&b_x;cx &&d_x* 

a_x 
ax 
b_x 
cx 
d_x 
dx 

一個*應觸發與刪除_複製,一個;一個簡單的linebreak。

我有一個SED腳本,首先插入換行符(包括;的操作),然後執行復制的多行模式,而不使用_

如果將多行模式移動到單獨的腳本文件中並管道執行換行符的指令輸出,則多行模式將起作用。

由於一些奇怪的原因,一個腳本文件不會做 - 這是我想要的維護的原因。

這裏的合併版本:

#!/bin/sed -f 
# Remove whitespaces 
s/\ //g 
# Linebreak on && 
s/\&\&/\ 
\&\&/g 
### Linebreak on ; 
s/\;/\ 
/g 
# Remove extra new line 
s/\n// 
:extendvars 
/^..*\*$/ { 
    l       //DEBUG SWITCH 
    h 
    s/\(\&\|\*\)\(\&\|\*\)*//g 
    p 
    g 
    s/\(\&\|_\|-\|\*\)\(\&\|_\|-\|\*\)*//g 
    p 
    d 
    bextendvars; 
} 

調試開關「L」的多模式應該只匹配帶*號結束行的第一線,但所有線路和輸出

&&a_x*\n&&b_x\bx\n&&c_x*$ 

匹配在錯誤的組合版本中。當管道它,sed的正確識別圖案:

&&a_x*$ ... &&c_x*$ 

故障輸出(合併版本):

&&a_x*\n&&b_x\nbx\n&&c_x*$ 
a_x 
b_x 
bx 
c_x 
ax 
bx 
bx 
cx 

正確輸出中(管道版):

&&a_x*$ 
a_x 
ax 
&&b_x 
bx 
&&c_x*$ 
c_x 
cx 

我運行腳本

sed -f [SCRIPTNAME] <old >new 

在t他的版本我已經從&&b_x噴氣式飛機中刪除了&&

即使在一個腳本中執行所有語句,我如何才能讓SED識別正確的模式? 爲什麼SED突然不能匹配以*結尾的單行?

感謝您的幫助!

回答

1

你的代碼再也不會循環的原因實際上與循環條件沒有任何關係;這是在循環內部,你運行

d 

...它終止當前輸入行的處理。你在輸入行中在模式空間中構建了幾行是沒有意義的; d告訴sed停止它正在做的事情,閱讀下一行輸入(如果有的話)並重新開始。

無論如何,你的方法似乎對我來說過於複雜。我建議(在GNU的說法,因爲該機制在GNU sed的代碼更明顯)

#!/bin/sed -rf 

s/\s*(^|&&|;)\s*/\n/g  # split tokens onto several lines, make sure 
          # there's a newline in front of each (so the next 
          # regex matches all) 
s/(\n[^\n])_x\*/\1_x\1x/g # Match lines that end with _x*, expand to 
          # \nfoo_x\nfoox 
s/^\n*//     # remove leading newlines (we put at least one 
          # there in the beginning) 

你似乎已經不厭其煩地讓非GNU的代碼工作的sed,所以這裏有一個POSIX版本那是做同樣的事情:

#!/bin/sed -f 

s/[[:space:]]*&&[[:space:]]*/\ 
/g 
s/[[:space:]]*;[[:space:]]*/\ 
/g 
s/^/\ 
/
s/\(\n[^\n]\)_x\*/\1_x\1x/g 
s/^\ 
*// 

這消除了令牌周圍的空格。這似乎是一個明智的做法。如果你不希望發生這種情況,那麼必須從代碼中刪除空格匹配部分,並且必須爲令牌行末尾的空白符做準備。

#!/bin/sed -rf 

s/^|&&|;/\n/g 
s/(\n[^\n])_x\*([[:blank:]]*)/\1_x\1x\2/g 
s/^\n// 

是對GNU sed代碼的一種可能的修改。

+0

完美,謝謝! –

1

簡單的awk比sed更具可讀性。試試這個awk命令:

s='&&a_x* &&b_x;cx &&d_x*' 

echo "$s" | awk -F '\\*' -v RS='&&|;' 'NF{s=$1;print s} NF==2{sub(/_/, "", s);print s}' 
a_x 
ax 
b_x 
cx 
d_x 
dx 
+1

哦,我喜歡那樣。閃亮的。值得注意的是,並非所有的awk都支持正則表達式(甚至是多字符)'RS',所以考慮到OP努力避免sed代碼中的GNUisms,我不確定這對他是否有效,但這是一個很好的方法對大多數人來說這種事情。 – Wintermute

+0

是的,我應該提到,它是gnu awk – anubhava

+1

是的確很有光澤,很酷的替代解決方案 - 我會把AWK放在我的名單上! –