Hur lägger jag till permanenta radnummer i en fil?

Jag har en textfil så här (använder gVim i Windows)

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

Jag vill lägga till ett nummer i varje rad i filen. Använd inte :set number utan att lägga till numret som text före varje rad, enligt följande, så numret är en del av filen.

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

Kommentarer

  • awk är förmodligen verktyget för det här jobbet. Men jag ’ m på Windows (suck).
  • Besvarade här redan , gör inget 🙂
  • Kanske .. Eller är det mer allmänt?
  • Det ’ liknar, men jag skulle inte vilja ’ vet inte vad som är permanenta radnummer. För det andra handlar den andra frågan om alla rader (och svaret gör det) för gVim i Windows specifikt och det här är enkel numrerad lista för ett stycke bara i vanlig vim.
  • Jag antar att det inlägget använder ” permanent ” ot anger att bufferten ska ändras och att siffrorna inte är ’ t något rent visuellt (samma som du). Anledningen till att ange gvim i Windows är att undvika externa verktyg som cat eller nl, som kan göra talrader, men inte ’ t allmänt tillgängligt i Windows (som OP indikerar från deras kommentar om awk). De två bästa lösningarna är ren Vim. Slutligen är alla rader mot ett par bara en fråga om val av intervall. Klart inte en stor fråga.

Svar

På rent Vim-sätt:

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

Förklaring:

:%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 \= och :help line().

Att använda ett uttryck i ersättningsdelen är väldigt kraftfullt och FWIW är en ganska bra startpunkt för vimscript.

Kommentarer

  • Hur kan jag lägga till det här mycket användbara kommandot i en tangentkarta i vimrc?
  • För att komma till ämnet vim för ersättning: :help sub-replace-expression

Svar

En trevlig sak med Vim-makron är att de kan återkalla (de kan åberopa sig själva ):

  1. Rensa ut register q: qqq
  2. Lägg till numret i första raden: ggI1. (glöm inte utrymmet!)
  3. Gå tillbaka till radens början och börja spela in ett makro: 0qq
  4. Kopiera numret:
  5. Flytta ner en rad och klistra in numret: +P
  6. Gå tillbaka till början av raden och öka siffran: 0<c-a>
  7. Gå tillbaka till början på raden (så att makrot inte går sönder när det blir dubbelsiffror!): 0
  8. Ring makrot en gång för att göra det rekursivt. Vid det här laget finns det fortfarande inget i register q, så ingenting kommer att hända: @q.
  9. Spara makrot: q
  10. Ring makrot en gång till och se gnistor flyga !: @@

Makrot kommer att Fortsätt sedan att anropa sig själv tills den når slutet av filen.

Du kan använda det rekursiva makrotricket för många andra liknande problem, så det är en bra att vara medveten om.

Om du av någon anledning inte vill använda ett rekursivt makro kan du utelämna steg 1 och 8 och använda ett antal för att köra makrot flera gånger, t.ex. 100@q kör makro q 100 gånger.

Kommentarer

  • Kraftfulla grejer, jag böjer mig för din behärskning. Makron är som svart magi för mig …
  • @ropata, ett makro är bara en sekvens av (mestadels) kommandon för normalt läge.
  • @romainl Jag tror att det ’ är bättre att tänka på det som en sekvens av tangenttryckningar .
  • @Rich, det kan vara en sekvens av många saker, inklusive ex-kommandon.
  • @romainl Ja, det är ’ varför jag tycker att det ’ är bäst att tänka på det som tangenttryckningar. Den spelar exakt upp det du skriver på tangentbordet (inklusive, som du säger, ex-kommandon), som om du hade skrivit in allt manuellt.

Svar

Jag gillar att använda det globala kommandot vim för att utföra uppgifter som detta. Detta gäller för att lägga till iteration i början av en rad eller ändra en symbol i texten. Det ser mer komplicerat ut än de andra lösningarna, men är ett ganska flexibelt mönster att använda när du har det till hands och är lätt att ändra utan mycket tanke.

Välj först ditt sortiment (vilka linjer du vill tillämpa detta). Jag brukar använda märken (t.ex.ma på första raden och mb på den andra raden, men du kan också använda radnummer eller visuellt urval), ange sedan en ändring av följande kommando (för närvarande justerat för ditt användningsfall)

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

Dekonstruktion

:let i=1 

Detta ställer in variabel i med ett startvärde. Vanligtvis börjar listor med 1, så jag ställer in till 1.

| 

Baren startar ett nytt kommando

"a,"b 

Detta ställer in intervallet för nästa kommando. Jag går från mark a för att markera b , som skulle ställas in på den första raden och den sista raden i din lista.

g/^/ 

Detta är det globala kommandot. Den söker i filen (eller intervallet) efter ett visst reguljärt uttryck och kör resten av kommandoraden på varje av de rader som matchade. Jag matchar varje rad genom att söka efter ”början på raden”. Om du hade text som

Item some txt other text Item second item whatever Item third 

och bara vill sätta dessa etiketter framför Item och ignorera de andra raderna, gör g/Item/ eller g/^Item/ istället (förutsatt att den bokstavliga artikeltexten )

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

Detta kör det reguljära uttrycket för att ersätta början på raden med värdet i sammanfogad med a .. Generellt kan du göra detta till vad som helst (ersätt till exempel etiketten Item med numret).

|let i=i+1 

Även om fältet startar ett nytt kommando, sätter det upp ett andra kommando som ska köras inom det globala kommandot, istället för när det globala är klart. Resultatet är att vi ökar i innan nästa rad bearbetas av g. Här är en annan plats för flexibilitet. Modifieringen av i kan vara vad som helst (incre ment med 2, ring en funktion som genererar nästa element i Fibonacci-sekvensen, oavsett).

Svar

Lägg till nummer till alla rader

Det är möjligt att använda :%!nl -ba eller :%!cat -n kommandon som lägger till radnummer till alla rader.

På Windows, du ”har Cygwin / MSYS / SUA installerat.

Lägg till nummer till valda rader

För att bara lägga till nummer för valda rader, välj dem i visuellt läge ( v och markörer), sedan när du är klar – kör kommandot: :%!nl (ignorera tomma rader) eller :%!cat -n (tomma rader ingår).

Formatering

För att ta bort extra mellanslag, välj dem i visuellt block ( Ctrl + v ) och ta bort dem ( x ).

Om du vill lägga till några tecken (., :, ) efter siffrorna, välj dem i visuellt block ( Ctrl + v ) och lägg sedan till tecknet ( A , skriv tecknet och avsluta sedan med Esc ).

Kommentarer

  • Detta ger inte samma formatering som angiven i frågan. Jag gillar dock lösningens enkelhet.
  • @KarlYngveLerv å g Tack, inkluderade det i svaret.

Svar

En modifiering av romainl ”svar :

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

Detta kommer inte bara att lägga till radnummer, det kommer också att ersätta existerande radnummer om de redan finns där. Om du har infogat en rad i mitten, kommer den att omnummerera allt som förväntat.

Detta fungerar genom att ersätta valfritt nummer följt av a. Och ett mellanslag i början av raden med ett nytt nummer Detta kommer naturligtvis att brytas om du har en rad som redan börjar med det här mönstret, så använd med tanke.

Den tillagda delen:

  • ^ – Radens början
  • \( – Starta ny undergrupp
  • \d\+ – Matcha en siffra en eller flera gånger
  • \. – Matcha en punkt (.) och ett mellanslag .
  • \) – Avsluta undergrupp
  • \? – Gör gruppen valfri så att den fungerar som tidigare om det inte finns något nummer på den här raden ännu.

Bonustips :
För att ta bort radnumren kan du använda samma mönster med repalce-delen tom:

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

Svar

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

Det här numrerar de två första raderna och du kan trycka på @q för att numrera efterföljande rader (eller typ ex. 18@q om du vill nummer 20 rader totalt).

Förklaring:

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 

Fördelen med detta är att det inte kräver några externa kommandon, vilket är användbart om du ”re arbetar till exempel med Vim på Windows.

Kommentarer

  • När du har skrivit 1. <esc>h är du på andra kolumnen, inte första kolumnen. Jag skulle ersätta h med 0, varefter jag tycker att din lösning ska vara väldigt bra.
  • @KarlYngveLerv å g Oj, det var ett stavfel. Tack, fixa det.
  • Inga problem. Du har dock fortfarande inte uppdaterat förklaringen. Också: På många tangentbord väntar ^ på ett andra tecken för att tillåta skrivkombinationer som ^a -> â. Jag håller fortfarande med om att det är den bästa lösningen, men jag tycker att detta också bör nämnas.

Svar

I tycker att det valda svaret är det bästa, men i sprit av variation, jag kommer att erbjuda ett alternativ med hjälp av ett externt program:

:%!cat -n 

Detta filtrerar hela din buffert (som betecknas med %) genom det externa programmet, cat, där -n flaggan förbereder varje ingångsrad med ett radnummer.

Detta kräver naturligtvis att du har cat, vilket är sant för (förmodligen) alla Unix -liknande system.

Kolla in :help :range! för mer information om filtrering genom externa program.

Kommentarer

  • Jag inser att askaren använder gVim i Windows, så den här lösningen kommer förmodligen inte att vinna ’ där. Men jag tror att det fortfarande ger vissa möjligheter för andra t o lära av det.
  • Om du ’ har installerat msysgit och lagt till det i din PATH (IIRC det ’ är ett installationsalternativ), den här lösningen bör också fungera på Windows.
  • cat -n är inte POSIX, men nl är, så det kan vara en bättre alternativ.

Svar

Lite hackig lösning kan vara följande (allt skrivet mellan < och> ska infogas efter att du har tryckt på Ctrl + v ):

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

Dekonstruktion

:%normal {commands} 

kör kommandot för normalt läge på varje rad som anges av intervallet, i detta fall varje rad

:redir @" 

omdirigerar varje utdata som görs av ex-kommandon till den namnlösa bufferten.

:.= 

är ett ex-kommando som matar ut den aktuella raden siffra (med en föregående ny linje tyvärr)

:redir END 

slutar omdirigera till den namnlösa bufferten

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

infogar innehållet i den namnlösa bufferten med en. och en flik fram till varje rad och går ut från infogningsläget.

kdd 

går en rad uppåt och tar bort den nya raden som är resultatet av:. = kommando.

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *