2012-05-22 32 views
4

我有幾行我從excel轉換到維基,並希望爲每行上的文本部分添加鏈接標記,如果該字段中有文本。我已經開始轉換工作,到了這個地步:VIM:插入文本使用正則表達式

|10.20.30.9||x|-|| 
|10.20.30.10||x|s04|Server 4| 
|10.20.30.11||x|s05|Server 5| 
|10.20.30.12||||| 
|10.20.30.13||||| 

我想是到第四列從例如改變「s04」到「[[server:s04]]」。如果該行爲空或者包含「 - 」,我不希望添加鏈接括號。如果「 - 」是一個大問題,我可以刪除它。

我所有的嘗試正則表達式來取代行中的任何東西在整個行被取代。

+0

你可能不需要一個正則表達式。您可以簡單搜索並用「[[server:s04]]」替換「s04」,對嗎? –

+0

但我希望在與s04相同的列中有文本的所有行上添加文本,並且之前的列可能包含文本,因此可視塊不起作用。 – user1410444

+0

你應該考慮使用'awk',設置'|'作爲字段分隔符。 – ArjunShankar

回答

1

讓我推薦下面的替換命令。

:%s/^|\%([^|]*|\)\{3}\zs[^|-]\+\ze|/[[server:&]]/ 
+0

非常好!這可能是該問題的最簡單和最佳解決方案! – user1410444

+1

我注意到一個問題。包含一個或多個「 - 」的第4列中的任何條目都會得到圍繞第一個「 - 」部分的鏈接。由於我決定刪除所有隻有「 - 」的條目,因此正則表達式可以更改爲:%s/^ | \%([^ |] * | \)\ {3} \ zs [^ |] \ +/[ [服務器:&]]/ – user1410444

+0

@ user1410444:我可能弄錯了這部分規範。澄清問題:該命令是否應該忽略第四列*是連字符的行,或者是否包含連字符? –

4

考慮使用awk做到這一點:

#!/bin/bash 

awk -F'|' ' 
{ 
    OFS = "|"; 
    if ($5 != "" && $5 != "-") 
    $5 = "server:" $5; 
    print $0 
}' 

注:因爲第一個版本我已​​經編輯這個腳本。目前的這個,國際海事組織比較好。

然後你可以對其進行處理:

cat $FILENAME | sh $AWK_SCRIPTNAME 

-F'|'開關告訴awk使用|作爲一個字段分隔符。 if/elseprintf陳述很自我解釋。它打印字段,並在第5列前面加上'server:',只有它不是"-"""

爲什麼是第5列而不是第4列?:因爲您在每條記錄的開頭使用了|。所以awk採取「第一」字段($1)是一個空字符串,它認爲應該這首|之前已經發生

0

嘗試

:1,$s/|\(s[0-9]\+\)|/|[[server:\1]]|/ 

假設你的S04,S05總是S和一些

+0

mediawiki標記,因此替換應該是'| [[server:\ 1]] |' – rampion

+1

請注意,這將替換以下「| 10.20.30.11 | s04 | x | s05 | Server 5 |」中的第一個s04。 –

+0

@JohanSoderberg:是的,但我認爲輸入就像給出的例子,因此在第一列中不包含s03。但你當然是對的。 – dwalter

3

它可能更好,因爲ArjunShankar寫到AWK使用,但如果去掉這應該工作 「 - 」;)沒有得到它在那裏工作。

:%s/^\([^|]*|\)\([^|]*|\)\([^|]*|\)\([^|]*|\)\([^|]\+|\)/\1\2\3\4[[server:\5]]/ 

雖然這只是愚蠢的。前4個是相同的(匹配所有| 4次)。沒有讓它與{4}一起使用。第五個匹配s04/s05-strings(只是要求它不是空的,因此「 - 」必須被刪除)。

+0

更容易使用'\ {3}'來匹配前三個。你也可以使用'[^ ​​ - |] [^ |] *'來跳過只有'-'的情況。此外,請嘗試使用'\ zs'來避免完全使用第一部分::':%s/^ \%(| [^ |] * \)\ {3} \)| \ zs \([^ - |] [^ |] * \)/ [[server:\ 1]] /' – rampion

+0

+1將在'vim'中工作的答案 – ArjunShankar

+0

爲避免使用大量組,請嘗試使用'\ zs'和'\ ze' 。爲了只匹配單詞(solvind'-'issue),你可以使用下面的正則表達式:'\ w \ {1,}' –

4

這似乎做你放棄了那裏(與VIM)樣品的工作:

%s/^|\%([^|]*|\)\{3}\zs[^|]*/\=(empty(submatch(0)) || submatch(0) == '-') ? submatch(0) : '[[server:'.submatch(0).']]'/ 
+0

這工作就像一個魅力!我決定刪除 - 在現場,使取代更容易。 – user1410444

0

一個更簡單的替代可以實現這一目標:

%s/^|.\{-}|.\{-}|.\{-}|\zs\(\w\{1,}\)\ze|/[[server:\1]]/ 

    ^^^^^^^^^^^^^^^^^^^^     -> Match the first 3 groups (empty or not); 
         ^^^    -> Marks the "start of match"; 
          ^^^^^^^^^^^  -> Match only if the 4th line contains letters numbers and `_` ([0-9A-Za-z_]); 
            ^^^ -> Marks the "end of match"; 

如果_字符類似於-,可以出現但不能被替換,請使用以下正則表達式:%s/^|.\{-}|.\{-}|.\{-}|\zs\([0-9a-zA-Z]\{1,}\)\ze|/[[server:\1]]/

2

增加更多可讀性到想法gi被別人VEN:

:%s/\v^%(\|.{-}){3}\|\zs(\w+)/[[server:\1]]/ 

完成任務。

請注意{3}表示要跳過的列數。還請注意使用\v很神奇正則表達式模式。這減少了正則表達式的複雜度,特別是當它使用比文本文本更多的「特殊」字符時。

+0

不錯的一個!我完全忘記了我們可以使用{3}來減少重複次數。爲此投票! –

+0

這並沒有完全奏效。在第四欄爲空的一些行上,但第五欄中有文本,第五欄作爲鏈接。 – user1410444