Jeg har en tekstfil som denne (bruker gVim på Windows)
foo bar baz quux corge grault garply waldo fred plugh [...150 more lines...] xyzzy thud
Jeg vil legge til et nummer til hver linje i filen. Bruker ikke :set number
, men legger til nummeret som tekst foran hver linje, som følger, så tallet er en del av filen.
1. foo bar baz quux 2. corge grault garply 3. waldo fred plugh [...~150 more lines...] 155. xyzzy thud
Kommentarer
Svar
På ren Vim-måte:
:%s/^/\=line(".").". "
Forklaring:
:%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
Se :help \=
og :help line()
.
Å bruke et uttrykk i erstatningsdelen er veldig kraftig og FWIW et ganske bra inntakssted for vimscript.
Kommentarer
- Hvordan kan jeg legge til denne veldig nyttige kommandoen til et nøkkelkort i vimrc?
- For å komme til vim-hjelpemnet for erstatning:
:help sub-replace-expression
Svar
En fin ting med Vim-makroer er at de kan gjengi (de kan påberope seg selv ):
- Slett registeret q:
qqq
- Legg til nummeret i første linje:
ggI1.
(ikke glem plassen!) - Gå tilbake til start på linjen og begynn å registrere en makro:
0qq
- Kopier nummeret:
- Flytt nedover en linje og lim inn tallet:
+P
- Gå tilbake til starten av linjen og øk tallet:
0<c-a>
- Gå tilbake til begynnelsen av linjen (slik at makroen ikke går i stykker når den kommer til tosifrede!):
0
- Ring makroen en gang, for å gjøre den rekursiv. På dette punktet er det fortsatt ingenting i registeret q, så ingenting vil skje:
@q
. - Lagre makroen:
q
- Ring makroen en gang til, og se gnistene fly !:
@@
Makroen vil fortsett deretter å påkalle seg selv til den når slutten av filen.
Du kan bruke det rekursive makrotrikset for mange andre lignende problemer, så det er en god å være klar over.
Hvis du ikke vil bruke en rekursiv makro av en eller annen grunn, kan du utelate trinn 1 og 8 og bruke et antall for å kjøre makroen flere ganger, f.eks. 100@q
kjører makro q
100 ganger.
Kommentarer
- Kraftige ting, jeg bøyer meg for mestring. Makroer er som svart magi for meg …
- @ropata, en makro er bare en sekvens av (for det meste) normale moduskommandoer.
- @romainl Jeg tror det ‘ er bedre å tenke på det som en sekvens av tastetrykk .
- @Rich, det kan være en sekvens av mange ting, inkludert eks-kommandoer.
- @romainl Ja, det er ‘ hvorfor jeg tror det ‘ er best å tenke på det som tastetrykk. Den spiller nøyaktig hva du skriver på tastaturet (inkludert, som du sier, ex-kommandoer), som om du hadde skrevet alt inn manuelt.
Svar
Jeg liker å bruke den globale kommandoen vim til å utføre oppgaver som dette. Dette gjelder for å legge til iterasjon i begynnelsen av en linje eller endre et symbol i teksten. Det ser mer komplisert ut enn de andre løsningene, men er et ganske fleksibelt mønster å bruke når du har det praktisk, og er enkelt å endre uten mye tanke.
Velg først ditt utvalg (hvilke linjer du vil bruke dette). Jeg bruker vanligvis merker (f.eks.ma
på første linje og mb
på den andre linjen, men du kan også bruke linjenumre eller visuelt valg), og skriv deretter inn en modifikasjon av følgende kommando (for øyeblikket justert for din brukstilfelle)
:let i=1|"a,"bg/^/s/^/\=i.". "/|let i=i+1
Dekonstruksjon
:let i=1
Dette setter opp variabelen i
med en startverdi. Vanligvis starter lister med 1, så jeg setter i til 1.
|
Linjen starter en ny kommando
"a,"b
Dette angir rekkevidden til neste kommando. Jeg går fra mark a
for å markere b
, som vil bli satt på første linje og siste linje i listen din.
g/^/
Dette er den globale kommandoen. Den søker i filen (eller området) etter et gitt regulært uttrykk, og utfører resten av kommandolinjen på hver av linjene som samsvarer. Jeg samsvarer med hver linje ved å søke etter «begynnelsen på linjen». Hvis du hadde tekst som
Item some txt other text Item second item whatever Item third
og bare vil sette disse etikettene foran Item
og ignorere de andre linjene, gjør g/Item/
eller g/^Item/
i stedet (forutsatt den bokstavelige vareteksten )
s/^/\=i.". "/
Dette utfører det regulære uttrykket for å erstatte begynnelsen av linjen med verdien i
sammenkoblet med a .
. Generelt kan du gjøre dette mot hva som helst (erstatt for eksempel etiketten Item
med tallet).
|let i=i+1
Selv om linjen starter en ny kommando, setter den opp en ny kommando som skal kjøres innenfor den globale kommandoen, i stedet for etter at den globale er fullført. Resultatet er at vi øker i
før neste linje behandles av g. Her er et annet sted for fleksibilitet. Modifikasjonen av i kan være hva som helst (incre ment ved 2, ring en funksjon som genererer det neste elementet i Fibonacci-sekvensen, uansett).
Svar
Legg til tall i alle linjer
Det er mulig å bruke :%!nl -ba
eller :%!cat -n
kommandoer som vil legge til linjenumre til alle linjene.
På Windows «har Cygwin / MSYS / SUA installert.
Legg til tall i valgte linjer
For å legge til tall bare for valgte linjer, vennligst velg dem i visuell modus ( v og markører), så når du er ferdig – utfør kommandoen: :%!nl
(ignorere blanke linjer) eller :%!cat -n
(blanke linjer inkludert).
Formatering
For å fjerne ekstra mellomrom, velg dem i visuell blokk ( Ctrl + v ) og fjern dem ( x ).
For å legge til noen tegn (.
, :
, ) etter tallene, velg dem i visuell blokk ( Ctrl + v ), og legg deretter til tegnet ( A , skriv inn tegnet, og avslutt med Esc ).
Kommentarer
- Dette gir ikke den samme formateringen som gitt i spørsmålet. Jeg liker likevel enkelheten i løsningen.
- @KarlYngveLerv å g Takk, inkluderte det i svaret.
Svar
En modifisering av romainl «svar :
:%s/^\(\d\+\. \)\?/\=line(".").". "
Dette vil ikke bare legge til linjenumre, det vil også erstatte spennende linjenumre hvis de allerede er der. Hvis du har satt inn en linje midtveis, nummererer den alt som forventet.
Dette fungerer ved å erstatte et hvilket som helst nummer etterfulgt av a. Og et mellomrom i begynnelsen av linjen med et nytt nummer. Dette vil åpenbart bryte hvis du har en linje som allerede begynner med dette mønsteret, så bruk med tanke.
Den tilføyde delen:
-
^
– Start av linje -
\(
– Start ny undergruppe -
\d\+
– Match et siffer en gang eller mer -
\.
– Match en prikk (
.
) og et mellomrom.
-
\)
– Slutt undergruppe -
\?
– Gjør gruppen valgfri, slik at den fungerer som før hvis det ikke er noe tall på denne linjen ennå.
Bonushint :
For å fjerne linjenumrene, kan du bruke det samme mønsteret med repalce-delen tom:
:%s/^\(\d\+\. \)\?//
Svar
I1. <esc>^qqyWjP^<C-a>q
Dette nummererer de to første linjene, og du kan trykke @q
for å nummerere påfølgende linjer (eller skriv ex. 18@q
hvis du vil nummerere 20 linjer totalt).
Forklaring:
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
Fordelen med dette er at det ikke krever noen eksterne kommandoer, noe som er nyttig hvis du » jobber med Vim på Windows, for eksempel.
Kommentarer
- Etter å ha skrevet
1. <esc>h
er du på andre kolonne, ikke første kolonne. Jeg vil erstatteh
med0
, hvoretter jeg synes løsningen din skal være veldig bra. - @KarlYngveLerv å g Whoops, det var en skrivefeil. Takk, fikset det.
- Ikke noe problem. Imidlertid har du fortsatt ikke oppdatert forklaringen. Også: På mange tastaturer venter
^
på et andre tegn for å tillate skrivekombinasjoner som^a -> â
. Jeg er fortsatt enig i at det er den beste løsningen, men jeg mener at dette også bør nevnes.
Svar
I synes det valgte svaret er det beste, men når det gjelder variasjon, vil jeg tilby et alternativ ved hjelp av et eksternt program:
:%!cat -n
Dette filtrerer hele buffer (som betegnet med %
) gjennom det eksterne programmet, cat
, der -n
flagg forbereder hver linje med inngang med et linjenummer.
Dette krever selvfølgelig at du har cat
installert, noe som gjelder for (sannsynligvis) alle Unix -lignende systemer.
Ta en titt på :help :range!
for mer informasjon om filtrering gjennom eksterne programmer.
Kommentarer
- Jeg er klar over at spørgeren bruker gVim på Windows, så denne løsningen vant sannsynligvis ‘ ikke å jobbe der. Imidlertid tror jeg det fortsatt gir litt mulighet for andre t o lær av det.
- Hvis du ‘ har installert
msysgit
og lagt det til PATH (IIRC det ‘ er et installasjonsalternativ), bør denne løsningen også fungere på Windows. -
cat -n
er ikke POSIX, mennl
er, så det kan være en bedre alternativ.
Svar
En litt hackish løsning kan være følgende (alt skrevet mellom < og> skal settes inn etter å ha trykket på Ctrl + v ):
:%normal :redir @"<Enter>:-=<Enter>:redir END<Enter>I<C-R>".<Tab><Esc>kdd
Dekonstruksjon
:%normal {commands}
kjører kommandoen for normalmodus på hver linje spesifisert av området, i dette tilfellet hver linje
:redir @"
omdirigerer hver utgang laget av ex-kommandoer til den ikke-navngitte bufferen.
:.=
er en ex-kommando som sender ut gjeldende linje Nummer (med en forrige ny linje dessverre)
:redir END
slutter å omdirigere til den navnløse bufferen
I<C-R>".<Tab><Esc>
setter inn innholdet i den navnløse bufferen med en. og en fane til foran hver linje og går ut av innsettingsmodus.
kdd
går en linje opp og fjerner den nye linjen som er resultatet av:. = kommando.
awk
er sannsynligvis verktøyet for denne jobben. Men jeg ‘ m på Windows (sukk).cat
ellernl
, som kan gjøre tallinjer, men ikke er ‘ t generelt tilgjengelig på Windows (som OP indikerer fra deres kommentar omawk
). De to beste løsningene er ren Vim. Til slutt er alle linjer mot en para bare et spørsmål om rekkevidde. Klart ikke et stort problem.