2013-02-10 10 views
6

मैं पाठ की पंक्तियों के तीन समूहों को अंतःस्थापित करने की कोशिश कर रहा हूं। उदाहरण के लिएअंतरण लाइनों vim

a 
a 
a 
b 
b 
b 
c 
c 
c 

से जाने के लिए

a 
b 
c 
a 
b 
c 
a 
b 
c 

वहाँ ऐसा करने का एक कारगर तरीका है?

+0

क्या यह वास्तविक दुनिया की स्थिति है या परीक्षण का मामला कम है? – romainl

+0

कम परीक्षण केस। ऐसे तीन समूह हैं जिन्हें अंतःस्थापित करने की आवश्यकता है लेकिन प्रत्येक में 3 आइटम लंबे समय तक हैं। मैं एक मैक्रो सही कर सकता था लेकिन मैं सोच रहा था कि वहां बेहतर तरीका हो सकता है: जी और – jpiasetz

+0

हम्म को ले जाएं, यदि सभी 'ए' समान हैं और 'बी' समान हैं और 'सी' समान हैं I डी बस पहले 'abc' मैन्युअल रूप से ऑर्डर करें (':/b/m।',':/c/m.') और परिणामी ब्लॉक को 3 बार डुप्लिकेट करें (जो कि जल्दी है) लेकिन आपकी असली दुनिया की ज़रूरतें शायद अधिक जटिल हैं। – romainl

उत्तर

0

यहाँ एक "oneliner" (लगभग) है, लेकिन आप, हर अद्वितीय लाइन शून्य से 1 के लिए यह फिर से करना अपने उदाहरण में 2 बार की है। शायद कोई उपयोग नहीं, लेकिन मुझे लगता है कि वीआईएम में पैटर्न के बारे में और जानने के लिए यह एक अच्छा अभ्यास था। जब तक पूरी लाइन अद्वितीय नहीं होती है (उदाहरण के लिए mno और mnp दो अद्वितीय रेखाएं हैं) यह सभी प्रकार की लाइनों को संभालती है।

सबसे पहले इस बात का यकीन है कि (और कर/ लाइन में कुछ भी, या कुछ और करने के लिए मैप किया गया है नहीं):

:set nowrapscan 

फिर नक्शा उदा इन ( पुनरावर्ती होना चाहिए, नहींnnoremap):
<C-R> और <CR>सचमुच लिखे जाने चाहिए।
\v पैटर्न में "बहुत जादू" का अर्थ है, @! ऋणात्मक रूप से आगे बढ़ना। \2 दूसरे कोष्ठक में जो मिला है उसका उपयोग करें। क्योंकि यह आपके उदाहरण में, ले जाता है 2 बार

:nmap ,. "xy$/\v^<C-R>x$<CR>:/\v^(<C-R>x)@!(.*)$\n(\2)$/m-<CR>j,. 
:nmap ,, gg,. 

फिर ,, रूप में कई बार करते हैं। सभी b एस और सभी c एस के लिए एक।


संपादित करें: मानचित्रण की विवरण। मैं इस प्रश्न में उदाहरण का उपयोग करूंगा जैसे कि यह इस मैपिंग के साथ एक बार चला गया है।
एक रन के बाद:

1. a 
2. b 
3. a 
4. b 
5. a 
6. b 
7. c 
8. c 
9. c 

कर्सर पिछले a (लाइन 5), जब ,, टाइपिंग, यह पहली वापस पहली पंक्ति के लिए, जाना पर तो है और फिर ,. के लिए मानचित्रण चलाता है, और है कि मानचित्रण कर रही है यह:

"xy$    # yanks current line (line 1) to reg. "x" ("a") " 
/\v^<C-R>x$<CR> # finds next line matching reg. "x" ("a" at line 3) 
:/\v^(<C-R>x)@!(.*)$\n(\2)$/m-<CR> 
# finds next line that have a copy under it ("c" in line 7) and moves that line 
# to current line (to line 3, if no "-" #after "m" it's pasted after current line) 
# Parts in the pattern: 
- ^(<C-R>x)@!(.*)$ # matches next line that don't start with what's in reg. "x" 
- \n(\2)$   # ...and followed by newline and same line again ("c\nc") 
- m-<CR>   # inserts found line at current line (line 3) 
j    # down one line (to line 4, where second "a" now is) 
,.    # does all again (recursive), this time finding "c" in line 8 
... 
,.    # gives error since there are no more repeated lines, 
       # and the "looping" breaks. 
5

कहीं मेरी ~/.vim फ़ाइलों की गहराई में मेरे पास :Interleave कमांड (नीचे जोड़ा गया) है। किसी भी तर्क के साथ :Interleave बस सामान्य के रूप में interleave होगा। 2 तर्कों के साथ यह कैसे निर्दिष्ट करेगा कि कितने समूह को एक साथ समूहीकृत किया जाना है। जैसे :Interleave 2 1 शीर्ष से 2 पंक्तियां लेंगे और फिर नीचे से 1 पंक्ति के साथ अंतःस्थापित करें।

अब आपकी समस्या को पहली पंक्ति के साथ शुरू और 1 पंक्ति एक पत्र c मिलान पहली पंक्ति ऊपर समाप्त होने को हल करने के

:1,/c/-1Interleave 
:Interleave 2 1 
  • 1,/c/-1 रेंज।
  • :1,/c/-1Interleave मूल रूप से a के समूहों बिछा की और b के
  • :Interleave 2 1 सीमा पूरी फ़ाइल इस समय है।
  • :Interleave 2 1c एस के समूह के साथ मिश्रित a और b के समूह को इंटरलीव करें। 2 से 1.

:Interleave कोड के मिश्रण अनुपात के साथ नीचे है।

command! -bar -nargs=* -range=% Interleave :<line1>,<line2>call Interleave(<f-args>) 
fun! Interleave(...) range 
    if a:0 == 0 
    let x = 1 
    let y = 1 
    elseif a:0 == 1 
    let x = a:1 
    let y = a:1 
    elseif a:0 == 2 
    let x = a:1 
    let y = a:2 
    elseif a:0 > 2 
    echohl WarningMsg 
    echo "Argument Error: can have at most 2 arguments" 
    echohl None 
    return 
    endif 
    let i = a:firstline + x - 1 
    let total = a:lastline - a:firstline + 1 
    let j = total/(x + y) * x + a:firstline 
    while j < a:lastline 
    let range = y > 1 ? j . ',' . (j+y) : j 
    silent exe range . 'move ' . i 
    let i += y + x 
    let j += y 
    endwhile 
endfun 
+0

दिलचस्प [क्रॉसलिंक] (http://vi.stackexchange.com/a/4576/2978)? ;) –

1

मैं आज रात इस मुद्दे में स्वतंत्र रूप से भाग गया। मेरा कुछ जवाबों के रूप में सुरुचिपूर्ण नहीं है, लेकिन मुझे लगता है कि यह समझना आसान है। यह कई धारणाएं बनाता है, तो यह एक हैक का एक सा है:)

  • एक यह वहाँ कुछ अद्वितीय चरित्र (या मनमाना चरित्र स्ट्रिंग) लाइनों में से किसी में नहीं मौजूद है मान लिया गया है - मैं नीचे @ मान।
  • बी) यह मानता है कि आप किसी भी ए, बी, या सी अनुभागों में किसी भी सफेद स्थान को पीछे या पीछे नहीं करना चाहते हैं।
  • सी) यह printf का उपयोग कर, आप आसानी से अधिकतम लाइन की लंबाई की पहचान कर सकते हैं, और फिर पैड सभी लाइनों है कि लंबाई (जैसे शायद% का उपयोग कर! Awk या आदि में मान लिया गया है)

    1. पैड रिक्त स्थान के साथ सभी लाइनें अधिकतम लंबाई तक।
    2. विजुअल केवल ए और बी अनुभागों का चयन करें, फिर %s/$/@
    3. सी अनुभाग से पहले बी अनुभाग को कॉपी करें और पिछला करें।
    4. ब्लॉक अनुभाग को कॉपी करें और बीसी अनुभाग से पहले एक सेक्शन पेस्ट करें।
    5. %s/@/\r
    6. %s/^ *//g
    7. %s/ *$//g
    8. लाइनों को हटाने के लिए छोड़ दिया है, जहां एक और ख वर्गों थे।
0

यदि आपके पास xclip आप लाइनों में कटौती और paste का उपयोग उन्हें बिछा कर सकते हैं:

  1. दृश्य लाइनों में से एक सेट का चयन
  2. प्रकार "+d उन्हें क्लिपबोर्ड से कट करने
  3. विजुअल लाइनों के दूसरे सेट का चयन करें
  4. टाइप !paste -d '\n' /dev/stdin <(xclip -o -selection clipboard)