Hoe voeg ik permanente regelnummers toe aan een bestand?

Ik heb een tekstbestand als dit (met gVim op Windows)

foo bar baz quux corge grault garply waldo fred plugh [...150 more lines...] xyzzy thud 

Ik wil een nummer toevoegen aan elke regel in het bestand. Gebruik geen :set number, maar om het nummer als tekst vóór elke regel toe te voegen, als volgt, zodat het nummer deel uitmaakt van het bestand.

1. foo bar baz quux 2. corge grault garply 3. waldo fred plugh [...~150 more lines...] 155. xyzzy thud 

Reacties

  • awk is waarschijnlijk de tool voor deze job. Maar ik ‘ m op Windows (zucht).
  • Beantwoord hier al , laat staan 🙂
  • Misschien .. of is dit algemener?
  • Het ‘ is vergelijkbaar, maar ik zou niet ‘ weet niet wat permanente regelnummers zijn. Ten tweede gaat de andere vraag over alle regels (en het antwoord doet dat) voor gVim op Windows specifiek en dit is een eenvoudige genummerde lijst voor slechts één alinea in gewone vim.
  • Nou, ik denk dat dat bericht ” permanent ” geeft niet aan dat de buffer moet worden gewijzigd en dat de nummers niet ‘ zijn t een puur visueel ding (hetzelfde als jij). De reden voor het specificeren van gvim op Windows is om externe hulpprogrammas zoals cat of nl te vermijden, die getallenregels kunnen gebruiken, maar niet ‘ t algemeen beschikbaar op Windows (zoals OP aangeeft uit hun opmerking over awk). De twee belangrijkste oplossingen zijn pure Vim. Ten slotte is alle regels versus één para slechts een kwestie van bereikselectie. Duidelijk geen groot probleem.

Antwoord

Op pure Vim-manier:

:%s/^/\=line(".").". " 

Uitleg:

:%s/^/ " the substitution will be applied to the beginning of every line \= " the rest of the replacement part is an expression line(".").". " " the expression returns the current line number concatenated with a dot and a space 

Zie :help \= en :help line().

Het gebruik van een uitdrukking in het vervangende deel is erg krachtig en FWIW is een redelijk goed toegangspunt tot vimscript.

Opmerkingen

  • Hoe kan ik deze zeer nuttige opdracht toevoegen aan een keymap in vimrc?
  • Om naar het vim-helponderwerp voor vervanging te gaan: :help sub-replace-expression

Answer

Een leuk ding over Vim-macros is dat ze kunnen recurseren (ze kunnen zichzelf ):

  1. Wis register q: qqq
  2. Voeg het nummer toe aan de eerste regel: ggI1. (vergeet de spatie niet!)
  3. Ga terug naar het begin van de regel en begin met het opnemen van een macro: 0qq
  4. Kopieer het nummer:
  5. Ga een regel omlaag en plak het nummer: +P
  6. Ga terug naar het begin van de regel en verhoog het nummer: 0<c-a>
  7. Ga terug naar het begin van de regel (dus de macro breekt niet wanneer het dubbele cijfers krijgt!): 0
  8. Roep de macro één keer aan om hem recursief te maken. Op dit punt staat er nog steeds niets in register q, dus er gebeurt niets: @q.
  9. Sla de macro op: q
  10. Roep de macro nog een keer aan en kijk hoe de vonken vliegen !: @@

De macro zal ga dan door met het aanroepen van zichzelf totdat het het einde van het bestand bereikt.

Je kunt de recursieve macro-truc gebruiken voor veel andere soortgelijke problemen, dus het is een goede om op te letten.

Als je om wat voor reden dan ook geen recursieve macro wilt gebruiken, kun je stap 1 en 8 overslaan en een count gebruiken om de macro meerdere keren uit te voeren, bijvoorbeeld 100@q zal macro q 100 keer uitvoeren.

Reacties

  • Krachtige dingen, ik buig voor je meesterschap. Macros zijn als zwarte magie voor mij …
  • @ropata, een macro is slechts een reeks (meestal) commandos in de normale modus.
  • @romainl Ik denk dat het ‘ is beter te zien als een reeks van toetsaanslagen .
  • @Rich, het kan een reeks van veel dingen zijn, inclusief ex-opdrachten.
  • @romainl Ja, dat ‘ is waarom ik denk dat het ‘ het beste is om het te beschouwen als toetsaanslagen. Het speelt precies af wat u op het toetsenbord typt (inclusief, zoals u zegt, ex-opdrachten), alsof u alles handmatig had ingetypt.

Antwoord

Ik gebruik graag het globale vim-commando om taken als deze uit te voeren. Dit is van toepassing op het toevoegen van iteratie aan het begin van een regel of het wijzigen van een symbool in de tekst. Het ziet er ingewikkelder uit dan de andere oplossingen, maar het is een behoorlijk flexibel patroon om te gebruiken als je het bij de hand hebt, en het is gemakkelijk aan te passen zonder veel na te denken.

Kies eerst je bereik (welke regels dit willen toepassen). Ik gebruik meestal markeringen (bijv.ma op de eerste regel en mb op de tweede, maar je kunt ook regelnummers of visuele selectie gebruiken) en voer vervolgens een wijziging in van het volgende commando (momenteel aangepast voor jouw situatie)

:let i=1|"a,"bg/^/s/^/\=i.". "/|let i=i+1 

Deconstructie

:let i=1 

Dit stelt variabele i in met een startwaarde. Gewoonlijk beginnen lijsten met 1, dus ik zet i op 1.

| 

De balk begint een nieuw commando

"a,"b 

Dit stelt het bereik van de volgende opdracht in. Ik” ga van mark a naar b , die zou worden ingesteld op de eerste regel en de laatste regel van uw lijst.

g/^/ 

Dit is het globale commando. Het doorzoekt het bestand (of bereik) voor een bepaalde reguliere expressie en voert de rest van de opdrachtregel uit op elk van de overeenkomende regels. Ik “pas elke regel aan door te zoeken naar” begin van regel “. Als u tekst als

Item some txt other text Item second item whatever Item third 

had en deze labels alleen vóór Item en negeer de andere regels, gebruik in plaats daarvan g/Item/ of g/^Item/ (uitgaande van de letterlijke itemtekst )

s/^/\=i.". "/ 

Dit voert de reguliere expressie uit om het begin van de regel te vervangen door de waarde van i samengevoegd met a .. Over het algemeen kunt u dit voor alles doen (vervang bijvoorbeeld het label Item door het nummer).

|let i=i+1 

Ook al begint de balk met een nieuw commando, het stelt een tweede commando in om binnen het globale commando uit te voeren, in plaats van nadat het globale is voltooid. Het resultaat is dat we verhogen i voordat de volgende regel wordt verwerkt door g. Hier is nog een plaats van flexibiliteit. De wijziging van i kan van alles zijn (incre ment door 2, roep een functie aan die het volgende element van de Fibonacci-reeks genereert, wat dan ook).

Answer

Voeg getallen toe aan alle regels

Het is mogelijk om :%!nl -ba of :%!cat -n opdrachten die regelnummers aan alle regels zullen toevoegen.

In Windows “moet Cygwin / MSYS / SUA geïnstalleerd hebben.

Voeg nummers toe aan geselecteerde regels

Om alleen nummers toe te voegen voor geselecteerde regels, selecteer ze dan in visuele modus ( v en cursors), en als u klaar bent – voer het commando uit: :%!nl (negeer lege regels) of :%!cat -n (inclusief lege regels).

Opmaak

Om extra spaties te verwijderen, selecteert u ze in visueel blok ( Ctrl + v ) en verwijder ze ( x ).

Om enkele karakters toe te voegen (., :, ) na de cijfers, selecteer ze in visueel blok ( Ctrl + v ), en voeg dan het karakter toe ( A , typ het karakter en eindig met Esc ).

Opmerkingen

  • Dit geeft niet dezelfde opmaak als gegeven in de vraag. Ik hou echter van de eenvoud van de oplossing.
  • @KarlYngveLerv å g Bedankt, dat is opgenomen in het antwoord.

Antwoord

Een wijziging van romainl “s antwoord :

:%s/^\(\d\+\. \)\?/\=line(".").". " 

Dit zal niet alleen regelnummers toevoegen , het zal ook bestaande regelnummers vervangen als ze er al zijn. Of, als je halverwege een regel hebt ingevoegd, wordt alles opnieuw genummerd zoals verwacht.

Dit werkt door elk nummer gevolgd door een. En een spatie aan het begin van de regel te vervangen door een nieuw nummer . Dit zal duidelijk breken als je een regel hebt die al met dit patroon begint, dus gebruik met gedachte.

Het toegevoegde deel:

  • ^ – Begin van regel
  • \( – Start nieuwe subgroep
  • \d\+ – Komt overeen met een of meer cijfers
  • \. – Komt overeen met een punt (.) en een spatie .
  • \) – Einde subgroep
  • \? – Maak de groep optioneel, zodat deze werkt zoals voorheen als er nog geen nummer op deze regel staat.

Bonushint :
Om de regelnummers te verwijderen , kunt u hetzelfde patroon gebruiken met het vervangende gedeelte leeg:

:%s/^\(\d\+\. \)\?// 

Answer

I1. <esc>^qqyWjP^<C-a>q 

Dit nummer de eerste twee regels, en u kunt op @q om volgende regels te nummeren (of typ ex. 18@q als je in totaal 20 regels wilt tellen).

Uitleg:

I1. <esc> Number the first line hqq Go back to the start of the line and start recording a macro yWjP Copy the line number to the next line ^<C-a> Increment the next line"s line number q Finish recording 

Het voordeel hiervan is dat het geen externe commandos nodig heeft, wat handig is als u werken met Vim op Windows, bijvoorbeeld.

Reacties

  • Na het typen van 1. <esc>h ben je op de tweede kolom, niet eerste kolom. Ik zou de h vervangen door 0, waarna ik denk dat je oplossing erg goed zou moeten zijn.
  • @KarlYngveLerv å g Oeps, dat was een typfout. Bedankt, het opgelost.
  • Geen probleem. U heeft de uitleg echter nog steeds niet bijgewerkt. Ook: op veel toetsenborden wacht ^ op een tweede teken om typecombinaties zoals ^a -> â toe te staan. Ik ben het er nog steeds mee eens dat dit de beste oplossing is, maar ik denk dat dit ook moet worden vermeld.

Antwoord

I denk dat het gekozen antwoord het beste is, maar in de geest van variatie, zal ik “een alternatief aanbieden met behulp van een extern programma:

:%!cat -n 

Dit filtert je hele buffer (zoals aangegeven door %) via het externe programma, cat, waarbij de -n vlag plaatst elke invoerregel met een regelnummer.

Dit vereist natuurlijk dat u cat hebt geïnstalleerd, wat geldt voor (waarschijnlijk) alle Unix -achtige systemen.

Bekijk :help :range! voor meer details over het filteren door externe programmas.

Opmerkingen

  • Ik realiseer me dat de vragensteller gVim op Windows gebruikt, dus deze oplossing zal daar waarschijnlijk ‘ niet werken. Maar ik denk dat het nog steeds een kans biedt voor anderen t o ervan te leren.
  • Als je ‘ msysgit hebt geïnstalleerd en dat hebt toegevoegd aan je PAD (IIRC it ‘ is een installatieoptie), zou deze oplossing ook moeten werken op Windows.
  • cat -n is niet POSIX, maar nl is, dus het kan een betere optie.

Answer

Een beetje hackachtige oplossing zou de volgende kunnen zijn (alles geschreven tussen < en> moeten worden ingevoegd na het drukken op Ctrl + v ):

:%normal :redir @"<Enter>:-=<Enter>:redir END<Enter>I<C-R>".<Tab><Esc>kdd 

Deconstructie

:%normal {commands} 

voert de normale modusopdracht uit op elke regel gespecificeerd door het bereik, in dit geval elke regel

:redir @" 

stuurt elke uitvoer gemaakt door ex-opdrachten door naar de naamloze buffer.

:.= 

is een ex-opdracht die de huidige regel uitvoert aantal (helaas met een voorafgaande nieuwe regel)

:redir END 

stopt met omleiden naar de naamloze buffer

I<C-R>".<Tab><Esc> 

voegt de inhoud van de naamloze buffer in met een. en een tab naar de voorkant van elke regel en verlaat de invoegmodus.

kdd 

gaat een regel omhoog en verwijdert de nieuwe regel die het resultaat is van de:. = commando.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *