Tips en Trucs 2018

De sed teksteditor

Wie in een script een tekstbestand zoals configuratiebestanden moet aanpassen, heeft sed (Streaming EDitor) nodig. Sed ontvangt de aan te passen tekst met behulp van een stream (gegevensstroom) afkomstig van andere opdrachten via pipes (> of |) of direct via de grep opdracht zelf. Sed past teksten aan via opties met editoropdrachten, dus zonder de tekst weer te geven.

Naast de vele geavanceerde mogelijkheden heeft sed vijf basisfuncties. Je kunt je dus best eerst concentreren op deze vijf basisfuncties:

  1. Zoeken
  2. Vervangen
  3. Verwijderen
  4. Toevoegen
  5. Aanpassen/Omvormen

Werken met sed

Om de werking van sed te demonstreren met voorbeelden, maken we als volgt een voorbeeld tekstbestand aan:

dany@pindabook:~> grep --help | head -25 > grephelp.txt

Het tekstbestand grephelp.txt bevat eerste 25 regels van de instructies om grep te gebruiken.

Zoeken

Zoeken naar een tekstfragment is een standaard functie van elke teksteditor en sed is daarbij geen uitzondering. Laten we onze voorbeeldtekst doorzoeken naar het woord 'PATROON':

dany@pindabook:~> sed -n 's/PATROON/PATROON/p' grephelp.txt
Gebruik:  grep [OPTIE...] PATROON [BESTAND...]
Zoekt naar PATROON in ieder gegeven BESTAND.
  -E, --extended-regexp     PATROON is een uitgebreide reguliere expressie
  -F, --fixed-strings       PATROON is een serie tekenreeksen,
  -G, --basic-regexp        PATROON is een gewone reguliere expressie (standaard)
  -P, --perl-regexp         PATROON is een reguliere Perl-expressie
  -e, --regexp=PATROON      dit PATROON gebruiken bij het zoeken

De -n optie voorkomt het automatisch weergeven (printen) van elke regel. Daardoor worden enkel de regels waarin de zoekterm voorkomt weergegeven. Zonder de -n optie wordt elke regel in de tekst weergegeven en de regels met de zoekterm nogmaals (dus dubbel).

De optie 's/PATROON/PATROON/p' bestaat uit vier onderdelen gescheiden door schuine strepen (slashes):

Vervangen

Bij het zoeken naar een tekstfragment kan je het gevonden tekstfragment vervangen door een ander tekstfragment met het derde gedeelte van de hierboven besproken zoekopdracht. Een voorbeeld:

dany@pindabook:~> sed -n 's/PATROON/Patroon/p' grephelp.txt
Gebruik:  grep [OPTIE...] Patroon [BESTAND...]
Zoekt naar Patroon in ieder gegeven BESTAND.
  -E, --extended-regexp     Patroon is een uitgebreide reguliere expressie
  -F, --fixed-strings       Patroon is een serie tekenreeksen,
  -G, --basic-regexp        Patroon is een gewone reguliere expressie (standaard)
  -P, --perl-regexp         Patroon is een reguliere Perl-expressie
  -e, --regexp=Patroon      dit PATROON gebruiken bij het zoeken

In het voorbeeld vervangen we het woord PATROON door het woord Patroon. Bekijk je echter de inhoud van het bestand grephelp.txt (bijvoorbeeld met de opdracht cat grephelp.txt dan merk je dat de inhoud van het tekstbestand niet werd aangepast. De sed opdracht heeft de resultaten standaard enkel weer op het scherm. Om de aangepaste tekst op te slaan, kan je deze doorsluizen (pipen) naar een nieuw bestand:

dany@pindabook:~> sed 's/PATROON/Patroon/' grephelp.txt > grephelp1.txt

Het bestand grephelp1.txt bevat dan de aangepaste tekst. Door de -n optie te laten vallen, wordt elke regel in het doelbestand geplaatst. En door de p te laten vallen, vermijden we dat elke aangepaste regel tweemaal wordt opgeslagen.

Om de zoekterm te laten vervangen door hetzelfde tekstfragment, kan je het & teken gebruiken. Gewoon zoeken, wordt dan:

dany@pindabook:~> sed -n 's/expressie/&/p' grephelp.txt
  -E, --extended-regexp     PATROON is een uitgebreide reguliere expressie
  -G, --basic-regexp        PATROON is een gewone reguliere expressie (standaard)
  -P, --perl-regexp         PATROON is een reguliere Perl-expressie

Een vervangopdracht waarbij de zoekterm voorkomt in de vervangtekst wordt dan:

dany@pindabook:~> sed -n 's/expressie/&s/p' grephelp.txt
  -E, --extended-regexp     PATROON is een uitgebreide reguliere expressies
  -G, --basic-regexp        PATROON is een gewone reguliere expressies (standaard)
  -P, --perl-regexp         PATROON is een reguliere Perl-expressies

Met deze opdracht wordt het woord expressie vervangen door het woord expressies (meervoud).

Wil je enkel de tweede (of zoveelste) zoekterm vervangen, dan kan je dit eveneens opgeven. Met de volgende opdracht vervang je enkel het tweede voorkomen van het minteken in elke regel door een *:

dany@pindabook:~> sed 's/-/*/2' grephelp.txt
Gebruik:  grep [OPTIE...] PATROON [BESTAND...]
  
Zoekt naar PATROON in ieder gegeven BESTAND.
  
    Voorbeeld:  grep -i 'hallo wereld' menu.h main.c

Keuze en interpretatie van het patroon:
  -E, *-extended-regexp     PATROON is een uitgebreide reguliere expressie
  -F, *-fixed-strings       PATROON is een serie tekenreeksen,
                              elke tekenreeks op een aparte regel
  -G, *-basic-regexp        PATROON is een gewone reguliere expressie (standaard)
  -P, *-perl-regexp         PATROON is een reguliere Perl-expressie
  -e, *-regexp=PATROON      dit PATROON gebruiken bij het zoeken
  -f, *-file=BESTAND        patronen uit dit BESTAND halen
  -i, *-ignore-case         verschil tussen hoofd- en kleine letters negeren
  -w, *-word-regexp         patronen komen alleen overeen met een heel woord
  -x, *-line-regexp         patronen komen alleen overeen met een hele regel
  -z, *-null-data           regels eindigen op 0-byte, niet op LF-teken

Diversen:
  -s, *-no-messages         foutmeldingen onderdrukken
  -v, *-invert-match        de niet-overeenkomende regels selecteren
  -V, *-version             programmaversie tonen en stoppen
      -*help                deze hulptekst tonen en stoppen

De s (search en substitute) zorgt dat sed zoekt naar mintekens om deze door * te vervangen. De daaropvolgende 2 zorgt dat enkel het tweede minteken indien aanwezig door een * wordt vervangen. Je ziet in de uitvoer van de hierboven uitgevoerde opdracht duidelijk dat enkel het tweede minteken in elke regel door een * werd vervangen.

Om alle mintekens in de regels door een * te vervangen, gebruik je g (global):

dany@pindabook:~> sed 's/-/*/g' grephelp.txt
Gebruik:  grep [OPTIE...] PATROON [BESTAND...]
  
Zoekt naar PATROON in ieder gegeven BESTAND.
  
    Voorbeeld:  grep *i 'hallo wereld' menu.h main.c

Keuze en interpretatie van het patroon:
  *E, **extended*regexp     PATROON is een uitgebreide reguliere expressie
  *F, **fixed*strings       PATROON is een serie tekenreeksen,
                              elke tekenreeks op een aparte regel
  *G, **basic*regexp        PATROON is een gewone reguliere expressie (standaard)
  *P, **perl*regexp         PATROON is een reguliere Perl*expressie
  *e, **regexp=PATROON      dit PATROON gebruiken bij het zoeken
  *f, **file=BESTAND        patronen uit dit BESTAND halen
  *i, **ignore*case         verschil tussen hoofd* en kleine letters negeren
  *w, **word*regexp         patronen komen alleen overeen met een heel woord
  *x, **line*regexp         patronen komen alleen overeen met een hele regel
  *z, **null*data           regels eindigen op 0*byte, niet op LF*teken

Diversen:
  *s, **no*messages         foutmeldingen onderdrukken
  *v, **invert*match        de niet*overeenkomende regels selecteren
  *V, **version             programmaversie tonen en stoppen
      **help                deze hulptekst tonen en stoppen

Je kunt sed-opties ook combineren. Om alle mintekens van het tweede voorkomen in het regel door een * te vervangen, gebruik je:

dany@pindabook:~> sed 's/-/*/2g' grephelp.txt
Gebruik:  grep [OPTIE...] PATROON [BESTAND...]
  
Zoekt naar PATROON in ieder gegeven BESTAND.
  
    Voorbeeld:  grep -i 'hallo wereld' menu.h main.c

Keuze en interpretatie van het patroon:
  -E, **extended*regexp     PATROON is een uitgebreide reguliere expressie
  -F, **fixed*strings       PATROON is een serie tekenreeksen,
                              elke tekenreeks op een aparte regel
  -G, **basic*regexp        PATROON is een gewone reguliere expressie (standaard)
  -P, **perl*regexp         PATROON is een reguliere Perl*expressie
  -e, **regexp=PATROON      dit PATROON gebruiken bij het zoeken
  -f, **file=BESTAND        patronen uit dit BESTAND halen
  -i, **ignore*case         verschil tussen hoofd* en kleine letters negeren
  -w, **word*regexp         patronen komen alleen overeen met een heel woord
  -x, **line*regexp         patronen komen alleen overeen met een hele regel
  -z, **null*data           regels eindigen op 0*byte, niet op LF*teken

Diversen:
  -s, **no*messages         foutmeldingen onderdrukken
  -v, **invert*match        de niet*overeenkomende regels selecteren
  -V, **version             programmaversie tonen en stoppen
      -*help                deze hulptekst tonen en stoppen

Verwijderen

Om een zoekterm uit de tekst te verwijderen, vervang je deze door niets. Zo verwijder je alle mintekens met de opdracht:

dany@pindabook:~> sed 's/-//g' grephelp.txt
Gebruik:  grep [OPTIE...] PATROON [BESTAND...]
  
Zoekt naar PATROON in ieder gegeven BESTAND.
  
    Voorbeeld:  grep i 'hallo wereld' menu.h main.c

Keuze en interpretatie van het patroon:
  E, extendedregexp     PATROON is een uitgebreide reguliere expressie
  F, fixedstrings       PATROON is een serie tekenreeksen,
                              elke tekenreeks op een aparte regel
  G, basicregexp        PATROON is een gewone reguliere expressie (standaard)
  P, perlregexp         PATROON is een reguliere Perlexpressie
  e, regexp=PATROON      dit PATROON gebruiken bij het zoeken
  f, file=BESTAND        patronen uit dit BESTAND halen
  i, ignorecase         verschil tussen hoofd en kleine letters negeren
  w, wordregexp         patronen komen alleen overeen met een heel woord
  x, lineregexp         patronen komen alleen overeen met een hele regel
  z, nulldata           regels eindigen op 0byte, niet op LFteken

Diversen:
  s, nomessages         foutmeldingen onderdrukken
  v, invertmatch        de nietovereenkomende regels selecteren
  V, version             programmaversie tonen en stoppen
      help                deze hulptekst tonen en stoppen

Toevoegen

Om een tekstregel toe te voegen na de regel met de gevonden zoekterm gebruik je a (add):

dany@pindabook:~> sed '/--/ a "De vorige regel bevat een dubbel minteken"' grephelp.txt
Gebruik:  grep [OPTIE...] PATROON [BESTAND...]
  
Zoekt naar PATROON in ieder gegeven BESTAND.
  
    Voorbeeld:  grep -i 'hallo wereld' menu.h main.c

Keuze en interpretatie van het patroon:
  -E, --extended-regexp     PATROON is een uitgebreide reguliere expressie
"De vorige regel bevat een dubbel minteken"
  -F, --fixed-strings       PATROON is een serie tekenreeksen,
"De vorige regel bevat een dubbel minteken"
                              elke tekenreeks op een aparte regel
  -G, --basic-regexp        PATROON is een gewone reguliere expressie (standaard)
"De vorige regel bevat een dubbel minteken"
  -P, --perl-regexp         PATROON is een reguliere Perl-expressie
"De vorige regel bevat een dubbel minteken"
  -e, --regexp=PATROON      dit PATROON gebruiken bij het zoeken
"De vorige regel bevat een dubbel minteken"
  -f, --file=BESTAND        patronen uit dit BESTAND halen
"De vorige regel bevat een dubbel minteken"
  -i, --ignore-case         verschil tussen hoofd- en kleine letters negeren
"De vorige regel bevat een dubbel minteken"
  -w, --word-regexp         patronen komen alleen overeen met een heel woord
"De vorige regel bevat een dubbel minteken"
  -x, --line-regexp         patronen komen alleen overeen met een hele regel
"De vorige regel bevat een dubbel minteken"
  -z, --null-data           regels eindigen op 0-byte, niet op LF-teken
"De vorige regel bevat een dubbel minteken"

Diversen:
  -s, --no-messages         foutmeldingen onderdrukken
"De vorige regel bevat een dubbel minteken"
  -v, --invert-match        de niet-overeenkomende regels selecteren
"De vorige regel bevat een dubbel minteken"
  -V, --version             programmaversie tonen en stoppen
"De vorige regel bevat een dubbel minteken"
      --help                deze hulptekst tonen en stoppen
"De vorige regel bevat een dubbel minteken"

Om een regel voor de gevonden zoekterm in te voegen, gebruik je i (insert):

dany@pindabook:~> sed '/--/ i "De volgende regel bevat een dubbel minteken"' grephelp.txt
Gebruik:  grep [OPTIE...] PATROON [BESTAND...]
  
Zoekt naar PATROON in ieder gegeven BESTAND.
  
    Voorbeeld:  grep -i 'hallo wereld' menu.h main.c

Keuze en interpretatie van het patroon:
"De volgende regel bevat een dubbel minteken"
  -E, --extended-regexp     PATROON is een uitgebreide reguliere expressie
"De volgende regel bevat een dubbel minteken"
  -F, --fixed-strings       PATROON is een serie tekenreeksen,
                              elke tekenreeks op een aparte regel
"De volgende regel bevat een dubbel minteken"
  -G, --basic-regexp        PATROON is een gewone reguliere expressie (standaard)
"De volgende regel bevat een dubbel minteken"
  -P, --perl-regexp         PATROON is een reguliere Perl-expressie
"De volgende regel bevat een dubbel minteken"
  -e, --regexp=PATROON      dit PATROON gebruiken bij het zoeken
"De volgende regel bevat een dubbel minteken"
  -f, --file=BESTAND        patronen uit dit BESTAND halen
"De volgende regel bevat een dubbel minteken"
  -i, --ignore-case         verschil tussen hoofd- en kleine letters negeren
"De volgende regel bevat een dubbel minteken"
  -w, --word-regexp         patronen komen alleen overeen met een heel woord
"De volgende regel bevat een dubbel minteken"
  -x, --line-regexp         patronen komen alleen overeen met een hele regel
"De volgende regel bevat een dubbel minteken"
  -z, --null-data           regels eindigen op 0-byte, niet op LF-teken

Diversen:
"De volgende regel bevat een dubbel minteken"
  -s, --no-messages         foutmeldingen onderdrukken
"De volgende regel bevat een dubbel minteken"
  -v, --invert-match        de niet-overeenkomende regels selecteren
"De volgende regel bevat een dubbel minteken"
  -V, --version             programmaversie tonen en stoppen
"De volgende regel bevat een dubbel minteken"
      --help                deze hulptekst tonen en stoppen

Aanpassen/Omvormen

Om de volledige regel met de zoekterm te vervangen, gebruik je c (change):

dany@pindabook:~> sed '/PATROON/ c Deze regel bevat geheime informatie' grephelp.txt
Deze regel bevat geheime informatie
  
Deze regel bevat geheime informatie
  
    Voorbeeld:  grep -i 'hallo wereld' menu.h main.c

Keuze en interpretatie van het patroon:
Deze regel bevat geheime informatie
Deze regel bevat geheime informatie
                              elke tekenreeks op een aparte regel
Deze regel bevat geheime informatie
Deze regel bevat geheime informatie
Deze regel bevat geheime informatie
  -f, --file=BESTAND        patronen uit dit BESTAND halen
  -i, --ignore-case         verschil tussen hoofd- en kleine letters negeren
  -w, --word-regexp         patronen komen alleen overeen met een heel woord
  -x, --line-regexp         patronen komen alleen overeen met een hele regel
  -z, --null-data           regels eindigen op 0-byte, niet op LF-teken

Diversen:
  -s, --no-messages         foutmeldingen onderdrukken
  -v, --invert-match        de niet-overeenkomende regels selecteren
  -V, --version             programmaversie tonen en stoppen
      --help                deze hulptekst tonen en stoppen

Bij transformaties (omvormen) kan je letters door andere letters vervangen, bijvoorbeeld om kleine letters naar hoofdletters om te zetten:

dany@pindabook:~> sed 'y/a/A/' grephelp.txt
Gebruik:  grep [OPTIE...] PATROON [BESTAND...]
  
Zoekt nAAr PATROON in ieder gegeven BESTAND.
  
    Voorbeeld:  grep -i 'hAllo wereld' menu.h mAin.c

Keuze en interpretAtie vAn het pAtroon:
  -E, --extended-regexp     PATROON is een uitgebreide reguliere expressie
  -F, --fixed-strings       PATROON is een serie tekenreeksen,
                              elke tekenreeks op een ApArte regel
  -G, --bAsic-regexp        PATROON is een gewone reguliere expressie (stAndAArd)
  -P, --perl-regexp         PATROON is een reguliere Perl-expressie
  -e, --regexp=PATROON      dit PATROON gebruiken bij het zoeken
  -f, --file=BESTAND        pAtronen uit dit BESTAND hAlen
  -i, --ignore-cAse         verschil tussen hoofd- en kleine letters negeren
  -w, --word-regexp         pAtronen komen Alleen overeen met een heel woord
  -x, --line-regexp         pAtronen komen Alleen overeen met een hele regel
  -z, --null-dAtA           regels eindigen op 0-byte, niet op LF-teken

Diversen:
  -s, --no-messAges         foutmeldingen onderdrukken
  -v, --invert-mAtch        de niet-overeenkomende regels selecteren
  -V, --version             progrAmmAversie tonen en stoppen
      --help                deze hulptekst tonen en stoppen

Hierbij worden alle kleine letters a naar hoofdletter A omgezet. Om verschillende letters gelijktijdig om te zetten, gebruik je letterreeksen. Let daarbij wel op de volgorde van de letters:

dany@pindabook:~> sed 'y/abdg/ABDG/' grephelp.txt
GeBruik:  Grep [OPTIE...] PATROON [BESTAND...]
  
Zoekt nAAr PATROON in ieDer GeGeven BESTAND.
  
    VoorBeelD:  Grep -i 'hAllo werelD' menu.h mAin.c

Keuze en interpretAtie vAn het pAtroon:
  -E, --extenDeD-reGexp     PATROON is een uitGeBreiDe reGuliere expressie
  -F, --fixeD-strinGs       PATROON is een serie tekenreeksen,
                              elke tekenreeks op een ApArte reGel
  -G, --BAsic-reGexp        PATROON is een Gewone reGuliere expressie (stAnDAArD)
  -P, --perl-reGexp         PATROON is een reGuliere Perl-expressie
  -e, --reGexp=PATROON      Dit PATROON GeBruiken Bij het zoeken
  -f, --file=BESTAND        pAtronen uit Dit BESTAND hAlen
  -i, --iGnore-cAse         verschil tussen hoofD- en kleine letters neGeren
  -w, --worD-reGexp         pAtronen komen Alleen overeen met een heel woorD
  -x, --line-reGexp         pAtronen komen Alleen overeen met een hele reGel
  -z, --null-DAtA           reGels einDiGen op 0-Byte, niet op LF-teken

Diversen:
  -s, --no-messAGes         foutmelDinGen onDerDrukken
  -v, --invert-mAtch        De niet-overeenkomenDe reGels selecteren
  -V, --version             proGrAmmAversie tonen en stoppen
      --help                Deze hulptekst tonen en stoppen

Tekstbestanden aanpassen

Om de aanpassingen in het bestand zelf door te voeren, gebruik je de -i optie (in-place). Om bijvoorbeeld het woord PATROON door Patroon in het tekstbestand zelf te vervangen, gebruik je:

sed in-place

Oefening baart kunst en ontdek de kracht van de sed opdracht.