Jeg har en tekstfil som denne (ved hjælp af gVim i Windows)
foo bar baz quux corge grault garply waldo fred plugh [...150 more lines...] xyzzy thud
Jeg vil tilføje et nummer til hver linje i filen. Brug ikke :set number
, men tilføjer nummeret som tekst forud for hver linje, som følger, så tallet er en del af 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åde:
:%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()
.
Brug af et udtryk i erstatningsdelen er meget kraftfuldt og FWIW er et ret godt indgangspunkt til vimscript.
Kommentarer
- Hvordan kan jeg føje denne meget nyttige kommando til et nøglekort i vimrc?
- For at komme til vim-hjælpemnet til erstatning:
:help sub-replace-expression
Svar
En god ting ved Vim-makroer er, at de kan tilbagekalde (de kan påberåbe sig selv ):
- Ryd registeret q:
qqq
- Føj nummeret til første linje:
ggI1.
(glem ikke pladsen!) - Flyt tilbage til start af linje og start optagelsen af en makro:
0qq
- Kopier nummeret:
- Flyt en linje ned og indsæt nummeret:
+P
- Gå tilbage til starten af linjen og forøg tallet:
0<c-a>
- Flyt tilbage til starten af linjen (så makroen ikke går i stykker, når den kommer til dobbelt tal!):
0
- Ring til makroen en gang for at gøre den rekursiv. På dette tidspunkt er der stadig intet i register q, så der sker ikke noget:
@q
. - Gem makroen:
q
- Ring til makroen en gang til, og se gnisterne flyve !:
@@
Makroen vil Fortsæt derefter med at påkalde sig selv, indtil den når slutningen af filen.
Du kan bruge det rekursive makro-trick til mange andre lignende problemer, så det er en god at være opmærksom på.
Hvis du af en eller anden grund ikke vil bruge en rekursiv makro, kan du udelade trin 1 og 8 og bruge et antal til at køre makroen flere gange, f.eks. 100@q
kører makro q
100 gange.
Kommentarer
- Kraftige ting, jeg bøjer mig for din mestring. Makroer er som sort magi for mig …
- @ropata, en makro er kun en sekvens af (for det meste) normale kommandoer.
- @romainl Jeg tror det ‘ er bedre at tænke på det som en sekvens af tastetryk .
- @Rich, det kan være en sekvens af mange ting, inklusive ex-kommandoer.
- @romainl Ja, det er ‘, hvorfor jeg synes, det ‘ er bedst at tænke på det som tastetryk. Det afspiller nøjagtigt det, du skriver på tastaturet (inklusive, som du siger, ex-kommandoer), som om du havde skrevet det hele manuelt.
Svar
Jeg kan godt lide at bruge den globale kommando vim til at udføre opgaver som denne. Dette gælder for at tilføje iteration til begyndelsen af en linje eller ændre et symbol i teksten. Det ser mere kompliceret ud end de andre løsninger, men er et ret fleksibelt mønster, du kan bruge, når du har det praktisk, og det er let at ændre uden meget tanke.
Vælg først dit sortiment (hvilke linjer du ønsker at anvende dette). Jeg bruger normalt mærker (f.eks.ma
på den første linje og mb
på den anden, men du kan også bruge linjenumre eller visuelt valg), og indtast derefter en ændring af følgende kommando (aktuelt justeret til din brugssag)
:let i=1|"a,"bg/^/s/^/\=i.". "/|let i=i+1
Dekonstruktion
:let i=1
Dette konfigurerer variabel i
med en startværdi. Normalt starter lister med 1, så jeg sætter jeg til 1.
|
Linjen starter en ny kommando
"a,"b
Dette indstiller rækkevidden for den næste kommando. Jeg går fra mark a
for at markere b
, som vil blive indstillet på den første linje og sidste linje på din liste.
g/^/
Dette er den globale kommando. Det søger i filen (eller området) efter et givet regulært udtryk og udfører resten af kommandolinjen på hver af de linjer, der matchede. Jeg matcher hver linje ved at søge efter “begyndelsen på linjen”. Hvis du havde tekst som
Item some txt other text Item second item whatever Item third
og kun vil sætte disse etiketter foran Item
og ignorere de andre linjer, gør g/Item/
eller g/^Item/
i stedet (forudsat den bogstavelige varetekst )
s/^/\=i.". "/
Dette udfører det regulære udtryk for at erstatte begyndelsen af linjen med værdien i
sammenkædet med a .
. Generelt kan du gøre dette overalt (udskift f.eks. etiketten Item
med nummeret).
|let i=i+1
Selvom bjælken starter en ny kommando, opretter den en anden kommando, der skal køre inden for den globale kommando, i stedet for efter at den globale er færdig. Resultatet er, at vi øger i
før den næste linje behandles af g. Her er et andet sted for fleksibilitet. Ændringen af i kan være hvad som helst (incre ment ved 2, kald en funktion, der genererer det næste element i Fibonacci-sekvensen, uanset hvad.).
Svar
Tilføj tal til alle linjer
Det er muligt at bruge :%!nl -ba
eller :%!cat -n
kommandoer, der tilføjer linjenumre til alle linjerne.
På Windows “skal Cygwin / MSYS / SUA installeres.
Tilføj numre til valgte linjer
Hvis du kun vil tilføje numre for valgte linjer, skal du vælge dem i visuel tilstand ( v og markører), så når du er færdig – udfør kommandoen: :%!nl
(ignorer blanke linjer) eller :%!cat -n
(blanke linjer inkluderet).
Formatering
For at fjerne ekstra mellemrum skal du vælge dem i visuel blok ( Ctrl + v ) og fjern dem ( x ).
For at tilføje nogle tegn (.
, :
, ) efter tallene, vælg dem i visuel blok ( Ctrl + v ), og tilføj derefter tegnet ( A , skriv tegnet, og afslut derefter med Esc ).
Kommentarer
- Dette giver ikke den samme formatering som givet i spørgsmålet. Jeg kan dog lide løsningens enkelhed.
- @KarlYngveLerv å g Tak, inkluderet det i svaret.
Svar
En ændring af romainls svar :
:%s/^\(\d\+\. \)\?/\=line(".").". "
Dette vil ikke bare tilføje linjenumre, det vil også erstatte udgående linjenumre, hvis de allerede er der. Hvis du har indsat en linje midtvejs, nummererer den alt som forventet.
Dette fungerer ved at erstatte ethvert tal efterfulgt af a. Og et mellemrum i starten af linjen med et nyt nummer Dette bryder naturligvis, hvis du har en linje, der allerede starter med dette mønster, så brug med tanke.
Den tilføjede del:
-
^
– Start af linje -
\(
– Start ny undergruppe -
\d\+
– Match et ciffer en eller flere gange -
\.
– Match et punkt (
.
) og et mellemrum.
-
\)
– Afslut undergruppe -
\?
– Gør gruppen valgfri, så den fungerer som før, hvis der endnu ikke er noget nummer på denne linje.
Bonus tip :
For at fjerne linjenumrene kan du bruge det samme mønster med repalce-delen tom:
:%s/^\(\d\+\. \)\?//
Svar
I1. <esc>^qqyWjP^<C-a>q
Dette nummererer de to første linjer, og du kan trykke på @q
for at nummerere efterfølgende linjer (eller skriv ex. 18@q
hvis du vil nummerere 20 linjer i alt).
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 ved dette er, at det ikke kræver nogen eksterne kommandoer, hvilket er nyttigt, hvis du ” arbejder f.eks. med Vim på Windows.
Kommentarer
- Efter at have skrevet
1. <esc>h
er du på anden kolonne, ikke første kolonne. Jeg ville erstatteh
med0
, hvorefter jeg synes, at din løsning skulle være meget god. - @KarlYngveLerv å g Whoops, det var en skrivefejl. Tak, fikset det.
- Intet problem. Du har dog stadig ikke opdateret forklaringen. Også: På mange tastaturer venter
^
på et andet tegn for at tillade typekombinationer som^a -> â
. Jeg er stadig enig i, at det er den bedste løsning, men jeg synes, dette også skal nævnes.
Svar
I synes det valgte svar er det bedste, men i det store udvalg, vil jeg tilbyde et alternativ ved hjælp af et eksternt program:
:%!cat -n
Dette filtrerer hele din buffer (som betegnet med %
) gennem det eksterne program, cat
, hvor -n
flag forud for hver linje af input med et linjenummer.
Dette kræver selvfølgelig, at du har cat
, hvilket er sandt for (sandsynligvis) alle Unix -lignende systemer.
Tjek :help :range!
for flere detaljer om filtrering gennem eksterne programmer.
Kommentarer
- Jeg er klar over, at askeren bruger gVim på Windows, så denne løsning vandt sandsynligvis ‘ ikke arbejde der. Dog tror jeg, det stadig giver nogle muligheder for andre t o lær af det.
- Hvis du ‘ har installeret
msysgit
og føjet det til din PATH (IIRC det ‘ er en installationsmulighed), denne løsning skal også fungere på Windows. -
cat -n
er ikke POSIX, mennl
er, så det kan være en bedre mulighed.
Svar
En smule hackish-løsning kan være følgende (alt skrevet mellem < og> skal indsættes efter tryk på Ctrl + v ):
:%normal :redir @"<Enter>:-=<Enter>:redir END<Enter>I<C-R>".<Tab><Esc>kdd
Dekonstruktion
:%normal {commands}
kører kommandoen til normal tilstand på hver linje specificeret af området, i dette tilfælde hver linje
:redir @"
omdirigerer alle output, der er lavet af ex-kommandoer, til den ikke-navngivne buffer.
:.=
er en ex-kommando, der udsender den aktuelle linje nummer (med en foregående ny linje desværre)
:redir END
stopper omdirigering til den ikke-navngivne buffer
I<C-R>".<Tab><Esc>
indsætter indholdet af den ikke-navngivne buffer med en. og en fane til foran hver linje og går ud af insert-tilstand.
kdd
går en linje op og fjerner den nye linje, som er resultatet af:. = kommando.
awk
er sandsynligvis værktøjet til dette job. Men jeg ‘ m på Windows (suk).cat
ellernl
, som kan udføre tallinjer, men ikke er ‘ t generelt tilgængelig på Windows (som OP angiver fra deres kommentar omawk
). De to bedste løsninger er ren Vim. Endelig er alle linjer vs en para bare et spørgsmål om rækkevidde. Klart ikke et stort problem.