Sådan bruges sed-kommandoen på Linux

Det lyder måske skørt, men Linux- sedkommandoen er en teksteditor uden en grænseflade. Du kan bruge det fra kommandolinjen til at manipulere tekst i filer og streams. Vi viser dig, hvordan du udnytter dens magt.

Kraften i sed

Den sedkommando er lidt ligesom skak: det tager en time at lære det grundlæggende og et helt liv at mestre dem (eller i det mindste en masse øvelse). Vi viser dig et udvalg af indledende gambits i hver af hovedkategorierne for sedfunktionalitet.

seder en streameditor, der fungerer på piped-input eller tekstfiler. Det har dog ikke en interaktiv teksteditorgrænseflade. Snarere giver du instruktioner til, at den skal følges, da den fungerer gennem teksten. Alt dette fungerer i Bash og andre kommandolinjeskaller.

Med sedkan du gøre alt følgende:

  • Vælg tekst
  • Erstat tekst
  • Føj linjer til tekst
  • Slet linjer fra tekst
  • Rediger (eller bevar) en original fil

Vi har struktureret vores eksempler til at introducere og demonstrere koncepter, ikke for at producere de tæreste (og mindst tilgængelige) sedkommandoer. Imidlertid sed afhænger mønstermatchning og tekstvalgfunktionalitet stærkt af regulære udtryk (regexes). Du får brug for noget fortrolighed med disse for at få det bedste ud af sed.

RELATERET: Sådan bruges regulære udtryk (regexes) på Linux

Et simpelt eksempel

Først skal vi bruge echotil at sende noget tekst til sedgennem et rør og sed erstatte en del af teksten. For at gøre det skriver vi følgende:

ekko howtogonk | sed 's / gonk / nørd /'

Den echokommando sender ”howtogonk” ind sed, og vores enkle substitution reglen ( ”s” står for udskiftning) anvendes. sed søger i inputteksten efter en forekomst af den første streng og erstatter eventuelle matches med den anden.

Strengen "gonk" erstattes af "nørd", og den nye streng udskrives i terminalvinduet.

Erstatninger er sandsynligvis den mest almindelige anvendelse af sed. Før vi kan dykke dybere ned i erstatninger, skal vi dog vide, hvordan man vælger og matcher tekst.

Valg af tekst

Vi har brug for en tekstfil til vores eksempler. Vi bruger et, der indeholder et udvalg af vers fra Samuel Taylor Coleridge's episke digt "The Rime of the Ancient Mariner."

Vi skriver følgende for at se på det med less:

mindre coleridge.txt

For at vælge nogle linjer fra filen giver vi start- og slutlinjerne for det område, vi vil vælge. Et enkelt nummer vælger den ene linje.

For at udtrække linjer en til fire skriver vi denne kommando:

sed -n '1,4p' coleridge.txt

Bemærk kommaet mellem 1og 4. Det pbetyder "udskriv matchede linjer." sed Udskriver som standard  alle linjer. Vi ville se al teksten i filen med de matchende linjer udskrevet to gange. For at forhindre dette bruger vi -n(stille) mulighed for at undertrykke den umatchede tekst.

Vi ændrer linjenumrene, så vi kan vælge et andet vers, som vist nedenfor:

sed -n '6,9p' coleridge.txt

Vi kan bruge indstillingen -e(udtryk) til at foretage flere valg. Med to udtryk kan vi vælge to vers som sådan:

sed -n -e '1,4p' -e '31, 34p 'coleridge.txt

Hvis vi reducerer det første tal i det andet udtryk, kan vi indsætte et tomt mellem de to vers. Vi skriver følgende:

sed -n -e '1,4p' -e '30, 34p 'coleridge.txt

Vi kan også vælge en startlinje og fortælle sed at gå gennem filen og udskrive alternative linjer hver femte linje eller springe et vilkårligt antal linjer over. Kommandoen svarer til dem, vi brugte ovenfor til at vælge et interval. Denne gang bruger vi dog en tilde ( ~) i stedet for et komma til at adskille tallene.

Det første tal angiver startlinjen. Det andet tal fortæller sedhvilke linjer efter startlinjen vi vil se. Nummeret 2 betyder hver anden linje, 3 betyder hver tredje linje osv.

Vi skriver følgende:

sed -n '1 ~ 2p' coleridge.txt

Du ved ikke altid, hvor den tekst, du leder efter, findes i filen, hvilket betyder, at linjenumre ikke altid vil være til stor hjælp. Du kan dog også bruge sed til at vælge linjer, der indeholder matchende tekstmønstre. Lad os for eksempel udtrække alle linjer, der starter med "Og".

Indsatsen ( ^) repræsenterer starten på linjen. Vi omslutter vores søgeudtryk i skråstreg ( /). Vi inkluderer også et mellemrum efter "Og", så ord som "Android" medtages ikke i resultatet.

Læsning af sedscripts kan være lidt hårde i starten. Det /p betyder "udskriv", ligesom det gjorde i de kommandoer, vi brugte ovenfor. I den følgende kommando er en skråstreg forud for den:

sed -n '/ ^ And / p' coleridge.txt

Tre linjer, der starter med "Og" udtrækkes fra filen og vises for os.

At foretage udskiftninger

I vores første eksempel viste vi dig følgende grundlæggende format til en sederstatning:

ekko howtogonk | sed 's / gonk / nørd /'

Det sfortæller, at sed dette er en erstatning. Den første streng er søgemønsteret, og den anden er teksten, som vi vil erstatte den matchede tekst med. Selvfølgelig, som med alle ting Linux, er djævelen i detaljerne.

Vi skriver følgende for at ændre alle forekomster af "dag" til "uge" og give mariner og albatross mere tid til at binde:

sed -n 's / dag / uge / p' coleridge.txt

I den første linje ændres kun den anden forekomst af "dag". Dette skyldes, at sedstopper efter den første kamp pr. Linje. Vi er nødt til at tilføje et "g" i slutningen af ​​udtrykket, som vist nedenfor, for at udføre en global søgning, så alle matches i hver linje behandles:

sed -n 's / dag / uge / gp' coleridge.txt

Dette matcher tre ud af de fire i første linje. Fordi det første ord er "dag" og sedskelner mellem store og små bogstaver, betragter det ikke den instans som den "dag".

Vi skriver følgende og tilføjer en i til kommandoen i slutningen af ​​udtrykket for at indikere store og små bogstaver:

sed -n 's / dag / uge / gip' coleridge.txt

Dette fungerer, men du vil måske ikke altid tænde sagsfølsomhed for alt. I disse tilfælde kan du bruge en regex-gruppe til at tilføje mønster-specifik sag-ufølsomhed.

For eksempel, hvis vi vedlægger tegn i firkantede parenteser ( []), fortolkes de som "ethvert tegn fra denne tegnliste."

Vi skriver følgende og inkluderer “D” og “d” i gruppen for at sikre, at den matcher både “Dag” og “dag”:

sed -n 's / [Dd] ay / week / gp' coleridge.txt

Vi kan også begrænse erstatninger til sektioner af filen. Lad os sige, at vores fil indeholder underlig afstand i det første vers. Vi kan bruge følgende velkendte kommando til at se det første vers:

sed -n '1,4p' coleridge.txt

Vi søger efter to mellemrum og erstatter dem med et. Vi gør dette globalt, så handlingen gentages over hele linjen. For at være tydelig er søgemønsteret mellemrum, mellemrum ( *), og erstatningsstrengen er et enkelt mellemrum. Den 1,4begrænser erstatningen til de første fire linjer i filen.

Vi sætter alt dette sammen i følgende kommando:

sed -n '1,4 s / * / / gp' coleridge.txt

Dette fungerer pænt! Søgemønsteret er det, der er vigtigt her. Stjernen ( *) repræsenterer nul eller flere af det foregående tegn, hvilket er et mellemrum. Således søger søgemønsteret efter strenge i et mellemrum eller mere.

Hvis vi erstatter et enkelt mellemrum for en række sekvenser med flere mellemrum, returnerer vi filen til regelmæssig afstand med et enkelt mellemrum mellem hvert ord. Dette vil i nogle tilfælde også erstatte et enkelt mellemrum med et enkelt mellemrum, men dette påvirker ikke noget negativt - vi får stadig det ønskede resultat.

Hvis vi skriver følgende og reducerer søgemønsteret til et enkelt mellemrum, ser du straks, hvorfor vi skal inkludere to mellemrum:

sed -n '1,4 s / * / / gp' coleridge.txt

Fordi stjernen matcher nul eller flere af det foregående tegn, ser den hvert tegn, der ikke er et mellemrum, som et "nulrum" og anvender erstatningen på det.

Men hvis vi inkluderer to mellemrum i søgemønsteret,  sedskal vi finde mindst et mellemrumstegn, før det anvender erstatningen. Dette sikrer, at tegn, der ikke er mellemrum, forbliver uberørte.

Vi skriver følgende ved hjælp af det -e(udtryk) vi brugte tidligere, hvilket giver os mulighed for at foretage to eller flere erstatninger samtidigt:

sed -n -e 's / motion / flutter / gip' -e 's / ocean / gutter / gip' coleridge.txt

Vi kan opnå det samme resultat, hvis vi bruger et semikolon ( ;) til at adskille de to udtryk, sådan:

sed -n 's / motion / flutter / gip; s / ocean / gutter / gip' coleridge.txt

Da vi byttede "dag" til "uge" i den følgende kommando, blev også forekomsten af ​​"dag" i udtrykket "godt en dag" byttet:

sed -n 's / [Dd] ay / week / gp' coleridge.txt

For at forhindre dette kan vi kun forsøge at erstatte linjer på et andet mønster. Hvis vi ændrer kommandoen for at have et søgemønster i starten, overvejer vi kun at arbejde på linjer, der matcher dette mønster.

Vi skriver følgende for at gøre vores matchende mønster til ordet "efter":

sed -n '/ after / s / [Dd] ay / week / gp' coleridge.txt

Det giver os det svar, vi ønsker.

Mere komplekse udskiftninger

Lad os give Coleridge en pause og bruge sedtil at udtrække navne fra etc/passwdfilen.

Der er kortere måder at gøre dette på (mere om det senere), men vi bruger den længere vej her til at demonstrere et andet koncept. Hver matchet vare i et søgemønster (kaldet underudtryk) kan nummereres (op til maksimalt ni poster). Du kan derefter bruge disse tal i dine  sedkommandoer til at henvise til specifikke underudtryk.

Du skal vedlægge underekspressionen i parentes [ ()] for at dette skal fungere. Parenteserne skal også være forud for en skråstreg ( \) for at forhindre dem i at blive behandlet som en normal karakter.

For at gøre dette skal du skrive følgende:

sed 's / \ ([^:] * \). * / \ 1 /' / etc / passwd

Lad os nedbryde dette:

  • sed 's/: Den sedkommando og begyndelsen af substitutionen ekspression.
  • \(: Den indledende parentes [ (], der omslutter underekspressionen, efterfulgt af et tilbageslag ( \).
  • [^:]*: Den første underekspression af søgeudtrykket indeholder en gruppe i parentes. Caret ( ^) betyder "ikke", når det bruges i en gruppe. En gruppe betyder, at ethvert tegn, der ikke er et kolon ( :), accepteres som et match.
  • \): Den afsluttende parentes [ )] med et foregående tilbageslag ( \).
  • .*: Denne anden søgeundekspression betyder "ethvert tegn og et hvilket som helst antal af dem."
  • /\1: Udskiftningsdelen af ​​udtrykket indeholder 1en backslash ( \). Dette repræsenterer den tekst, der matcher det første underekspression.
  • /': Det afsluttende skråstreg ( /) og enkelt citat ( ') afslutter sedkommandoen.

Hvad alt dette betyder er, at vi vil lede efter en række tegn, der ikke indeholder et kolon ( :), som vil være den første forekomst af matchende tekst. Derefter søger vi efter noget andet på den linje, som vil være den anden forekomst af matchende tekst. Vi erstatter hele linjen med den tekst, der matchede det første underudtryk.

Hver linje i /etc/passwdfilen starter med et kolon-afsluttet brugernavn. Vi matcher alt op til det første kolon, og erstatter derefter denne værdi for hele linjen. Så vi har isoleret brugernavne.

Dernæst omslutter vi det andet underudtryk i parentes [ ()], så vi også kan henvise til det med et tal. Vi erstatter også \1 med \2. Vores kommando erstatter nu hele linjen med alt fra det første kolon ( :) til slutningen af ​​linjen.

Vi skriver følgende:

sed 's / \ ([^:] * \) \ (. * \) / \ 2 /' / etc / passwd

Disse små ændringer vender betydningen af ​​kommandoen, og vi får alt undtagen brugernavne.

Lad os nu se på den hurtige og nemme måde at gøre dette på.

Vores søgeudtryk er fra det første kolon ( :) til slutningen af ​​linjen. Da vores erstatningsudtryk er tomt ( //), erstatter vi ikke den matchede tekst med noget.

Så vi skriver følgende og hugger alt fra det første kolon ( :) til slutningen af ​​linjen og efterlader kun brugernavne:

sed 's /:.*// "/ etc / passwd

Lad os se på et eksempel, hvor vi refererer til første og andet match i samme kommando.

Vi har en fil med kommaer ( ,), der adskiller for- og efternavne. Vi vil angive dem som "efternavn, fornavn." Vi kan  cat, som vist nedenfor, se, hvad der er i filen:

cat geeks.txt

Ligesom mange sedkommandoer kan denne næste se uigennemtrængelig ud i starten:

sed 's / ^ \ (. * \), \ (. * \) $ / \ 2, \ 1 / g' geeks.txt

Dette er en erstatningskommando som de andre, vi har brugt, og søgemønsteret er ret let. Vi nedbryder det nedenfor:

  • sed 's/: Den normale erstatningskommando.
  • ^: Fordi opslaget ikke er i en gruppe ( []), betyder det "Starten på linjen."
  • \(.*\),: Det første underudtryk er et hvilket som helst antal tegn. Det er omsluttet af parenteser [ ()], som hver forud for en skråstreg ( \), så vi kan henvise til det med et tal. Hele vores søgemønster hidtil oversættes som søgning fra starten af ​​linjen op til det første komma ( ,) efter et hvilket som helst antal af tegn.
  • \(.*\):  Det næste underudtryk er (igen) et hvilket som helst tal af et hvilket som helst tegn. Det er også omsluttet af parenteser [ ()], som begge er forud for et tilbageslag ( \), så vi kan henvise til den matchende tekst efter nummer.
  • $/: Dollartegnet ( $) repræsenterer slutningen af ​​linjen og tillader vores søgning at fortsætte til slutningen af ​​linjen. Vi har brugt dette simpelthen til at introducere dollartegnet. Vi har ikke rigtig brug for det her, da stjernen ( *) ville gå til slutningen af ​​linjen i dette scenarie. Det skråstreg fremad ( /) fuldender sektionen med søgemønster.
  • \2,\1 /g': Fordi vi lukkede vores to underudtryk i parentes, kan vi henvise til dem begge ved deres antal. Fordi vi vil vende ordren, skriver vi dem som second-match,first-match. Tallene skal indledes med et tilbageslag ( \).
  • /g: Dette gør det muligt for vores kommando at arbejde globalt på hver linje.
  • geeks.txt: Den fil, vi arbejder på.

Du kan også bruge kommandoen Klip ( c) til at erstatte hele linjer, der matcher dit søgemønster. Vi skriver følgende for at søge efter en linje med ordet "hals" i og erstatte den med en ny tekststreng:

sed '/ hals / c Omkring mit håndled var spændt' coleridge.txt

Vores nye linje vises nu i bunden af ​​vores uddrag.

Indsættelse af linjer og tekst

Vi kan også indsætte nye linjer og tekst i vores fil. For at indsætte nye linjer efter eventuelle matchende linjer bruger vi kommandoen Tilføj ( a).

Her er den fil, vi skal arbejde med:

cat geeks.txt

Vi har nummereret linjerne for at gøre dette lidt lettere at følge.

Vi skriver følgende for at søge efter linjer, der indeholder ordet "Han", og indsætte en ny linje under dem:

sed '/ Han / en -> Indsat!' geeks.txt

Vi skriver følgende og inkluderer kommandoen Indsæt ( i) for at indsætte den nye linje over dem, der indeholder matchende tekst:

sed '/ He / i -> indsat!' geeks.txt

Vi kan bruge ampersand ( &), som repræsenterer den oprindeligt matchede tekst, til at føje ny tekst til en matchende linje. \1 ,  \2osv., repræsenterer matchende underudtryk.

For at tilføje tekst til starten af ​​en linje bruger vi en erstatningskommando, der matcher alt på linjen kombineret med en erstatningsklausul, der kombinerer vores nye tekst med den originale linje.

For at gøre alt dette skriver vi følgende:

sed 's /.*/--> Indsat & /' geeks.txt

Vi skriver følgende, inklusive Gkommandoen, som tilføjer en tom linje mellem hver linje:

sed 'G' geeks.txt

Hvis du vil tilføje to eller flere tomme linjer, kan du bruge G;GG;G;Gosv.

Sletning af linjer

Slet-kommandoen ( d) sletter linjer, der matcher et søgemønster, eller dem, der er angivet med linjenumre eller områder.

For at slette den tredje linje skal vi f.eks. Skrive følgende:

sed '3d' geeks.txt

For at slette linieområdet fire til fem skal vi skrive følgende:

sed '4,5d' geeks.txt

For at slette linjer uden for et område bruger vi et udråbstegn ( !), som vist nedenfor:

sed '6,7! d' geeks.txt

Gemme dine ændringer

Indtil videre er alle vores resultater udskrevet i terminalvinduet, men vi har endnu ikke gemt dem nogen steder. For at gøre disse permanente kan du enten skrive dine ændringer til den originale fil eller omdirigere dem til en ny.

Overskrivning af din originale fil kræver en vis forsigtighed. Hvis din sedkommando er forkert, kan du muligvis foretage nogle ændringer i den originale fil, som er svære at fortryde.

For en vis ro i sindet sed kan du oprette en sikkerhedskopi af den originale fil, før den udfører kommandoen.

Du kan bruge stedet-indstillingen ( -i) til at fortælle, hvordan  seddu skriver ændringerne til den originale fil, men hvis du tilføjer en filtypenavn til den, sed sikkerhedskopieres den originale fil til en ny. Det har samme navn som den originale fil, men med en ny filtypenavn.

For at demonstrere søger vi efter alle linjer, der indeholder ordet “Han” og sletter dem. Vi sikkerhedskopierer også vores originale fil til en ny ved hjælp af BAK-udvidelsen.

For at gøre alt dette skriver vi følgende:

sed -i'.bak '' /^.*He.*$/d 'geeks.txt

Vi skriver følgende for at sikre, at vores sikkerhedskopifil er uændret:

cat geeks.txt.bak

Vi kan også skrive følgende for at omdirigere output til en ny fil og opnå et lignende resultat:

sed -i'.bak '' /^.*He.*$/d 'geeks.txt> new_geeks.txt

Vi bruger cattil at bekræfte, at ændringerne blev skrevet til den nye fil, som vist nedenfor:

kat new_geeks.txt

Efter at have sed All That

Som du sikkert har bemærket, er selv denne hurtige primer tændt sedret lang. Der er meget ved denne kommando, og der er endnu mere, du kan gøre med den.

Forhåbentlig har disse grundlæggende koncepter dog givet et solidt fundament, som du kan bygge på, når du fortsætter med at lære mere.