2015-10-18 42 views
0

我有一個這樣的文件:Vim中更換每第四個出現

Question 1 
b) answer b 
c) answer c 
a) answer a 
d) answer d 

Question 2 
a) answer a 
d) answer d 
b) answer b 
c) answer c 

Alls的答案是無序。我需要設置所有的第一答案(不管是什麼字母,只是他們的第一個答案),以v),其餘的x),所以輸出將是:

Question 1 
v) answer b 
x) answer c 
x) answer a 
x) answer d 

Question 2 
v) answer a 
x) answer d 
x) answer b 
x) answer c 

是否有可能有一個行命令?

+2

如果問題總是在一行中,並且總是有4個答案,那麼可以用一個宏來重複每個問題。否則,在Vim中這似乎很難,我可能會用Perl或Python代替。 –

+0

「四次發生」是什麼意思? –

+0

@DavidYoung我的原始方法是將'[a-d]'的位置替換爲4(1,4,8,...)到v)的倍數,然後將其餘部分替換爲'x)'。也許我正在反思它。 – user9090006

回答

0

你可以使用這樣的事情:

:%s/\d\+\_s\zs\l\ze)/v/ | %s/\D\_s\zs\l\ze)/x/ 

但這僅僅是爲您的特殊情況。

的解釋點點:在所有線路

  • \d\+一個或多個數字
    • %s替代
    • \_s空格或
    • \zs\ze開始和結束結束行比賽
    • \l小寫字母:[a-z]
    • \D非數字:[^0-9]
    • |可以用來分割命令,這樣就可以在一個給行多個命令。
    +1

    只有當文件字面上包含文本'問題1 \ n' ...'問題2 \ n'等等時,這纔會起作用。通常在這樣的問題中,示例中的文本僅僅是實際問題文本的佔位符,實際的答案文本......這只是OP的一個註釋,因此他們明白這隻會與在題。 –

    0

    如果你確實想要一條線。如果您使用足夠多的|將命令鏈接在一起,任何事情都可以製作成一個班輪。

    你可以做你自己的迭代並運行一個不同的替代命令,具體取決於你看到的模式的數量。

    :let i = 0 | g/^[abcd])/if i % 4 == 0 | s//v)/ | else | s//x)/ | endif | let i = i + 1 
    
    0

    如果所有問題的行數都相同,則可以這樣做。

    與光標在第一行的第一列開始(正常模式),你可以錄製宏(在這裏,爲a),會爲一個塊做到這一點:

    qajrvj^V}0rx'>)q 
    

    更細節:

    1. qa記錄在寄存器中的宏
    2. jrv向下移動一行,並用v
    3. 替換的第一個字符0
    4. j^V}(鍵入^ V作爲Ctrl-V)可視化塊選擇塊的其餘行的第一個字符
    5. 0確保我們在第0列(這很重要,如果我們遇到文件)
    6. rx用X代替這些字符
    7. '>轉到最後可視選擇結束
    8. )進入下一個句子(下一個問題的開始)
    9. q停止錄製宏

    這假定所有問題都在一行上(這將很容易改變),我們在宏運行時(也是一個非常小的改變來推廣這一點)在問題行的第一列和所有答案都是一條線(這種方法需要稍微改動一下,但總體來說這不會太難)。

    現在你可以再次運行@a(之後,@@重複上次運行的宏)。如果你想變成一個遞歸宏觀的(這將繼續運行,直到動作,可能是一個運動,失敗),您可以使用此遞歸調用追加到宏的結尾:

    [email protected] 
    

    使用大寫寄存器名稱意味着追加到該寄存器,而不是覆蓋它。如果您這樣做,並且所有問題都遵循這些限制條件,則只需運行一次該宏(手動)即可將此替換應用於整個文件。

    如果你想保留它以備後用,你也可以使用:normal命令將它變成一個函數。如果你這樣做,我會建議將它分散到幾個:normal命令中,並對它進行評論,就像我上面所做的一樣。