LX-SCR-INFO-awk-cut-sed
Updated 7/27/2010 00:45

awk cut sed

In de voorbije hoofdstukken hebben we telkens grote elementen behandeld van bash scripting: de  basis, variabelen en parameters, conditions met if en case, en loops met for en while. Er zijn echter belangrijke kleine tools die onontbeerlijk zijn om snel efficiënte bash scripts te bouwen. We bekijken er hier 3:

awk: de eerste letters van de namen Aho, Kernighan, and Weinberger vormen samen awk. Deze heren schreven awk in de jaren 70.
awk is een pattern scanning and processing language. Een programmeertaal op zich!
We gebruiken awk onder andere om snel enkelvoudige informatie te halen uit files of standaard output, met meerdere velden per regel en een scheidingsteken ertussen. Maar je kan er ook rapporten mee genereren. Of zelfs een editor mee bouwen.
awk is een zeer eenvoudige jedoch krachtige taal, waarmee je heel snel resultaten krijgt.

cut: cut is snijden in het engels. Met cut snijd je data uit tekstregels. Het is een eenvoudig te gebruiken commando. Je kan met awk hetzelfde doen als met cut, maar je kan met cut niet hetzelfde doen als met awk.

sed: staat voor streaming editor. Je kan sed gebruiken om "search and replace" opdrachten mee uit te voeren op files. Je kan er ook tekstregels mee filteren, en nog veel meer. Het is een editor zoals vim, maar gestuurd door de command line interface. Je kan er dus ook makros mee bouwen.

Het is niet mijn bedoeling, om alle mogelijkheden van deze 3 tools te bekijken. Daarvoor verwijs ik naar enkele engelstalige websites. Alleen het dagelijkse knip- en plakwerk wordt hier heel eventjes belicht, aan de hand van een paar voorbeelden.

  1. cut

    cut is de simpelste van de 3 tools uit dit hoofdstuk.

    de belangrijkste opties zijn

    -d  hierna volgt het scheidingsteken  (field separator of delimiter)
    -f  hierna volgt de kolom selector

    1. een voorbeeld:

      $ cut -d: -f1,6 /etc/passwd
      root:/root

      daemon:/usr/sbin

      bin:/bin

      sys:/dev

      sync:/bin

      games:/usr/games


      De passwd file wordt gelezen, scheidingsteken wordt gezet op : en de kolommen 1 en 6 worden op scherm gebracht.

    2. We breiden het commando wat uit, zodat het originele scheidingsteken vervangen wordt door een spatie en pipen het geheel naar column -t

      $ cut -d: -f1,6 --output-delimiter=" " /etc/passwd | column -t
      root               /root
      daemon             /usr/sbin
      bin                /bin
      sys                /dev
      sync               /bin
      games              /usr/games


      En dat ziet er heel netjes uit.

    3. En dan hebben we hier een cut to end of line:

      $ cut -d: -f6- /etc/passwd

      /root:/bin/bash

      /usr/sbin:/bin/sh

      /bin:/bin/sh

      /dev:/bin/sh

      /bin:/bin/sync

      /usr/games:/bin/sh


      De kracht van het minteken ...

    4. Of omgekeerd, een linkse cut:

      $ cut -d: -f-5 /etc/passwd
      root:x:0:0:root

      daemon:x:1:1:daemon

      bin:x:2:2:bin
      sys:x:3:3:sys
      sync:x:4:65534:sync
      games:x:5:60:games

    5. Dit kan ook:

      $ cut -c10-20 /etc/passwd
      0:root:/roo

      1:1:daemon:

      :bin:/bin:/

      :sys:/dev:/

      65534:sync:

      :60:games:/

      2:man:/var/


      Nu hebben we de karakters genummerd 10 tot 20 uit de passwd file gesneden.

  2. awk:

    1. We beginnen met een awk commando dat een gelijkaardig resultaat oplevert als ons eerste voorbeeld met cut.

      $ cat /etc/passwd | awk -F: '{print $1,$6}'

      root /root

      daemon /usr/sbin

      bin /bin

      sys /dev

      sync /bin

      games /usr/games


      We pipen de output van cat /etc/passwd (dat is dus de hele file) naar de awk-processor. awk draait het programma print $1,$6. Dit programma print de eerste en de zesde kolom van de gepipe-te file. Scheidingsteken wordt ingesteld met -F.

    2. $ awk -F':' '{ print $1,$6 }' /etc/passwd

      levert hetzelfde resultaat, dit keer zonder pipe.

    3. $ awk -F: '$3 == 0 { print $0 }' /etc/passwd
      root:x:0:0:root:/root:/bin/bash

      Een commando om de derde kolom te vergelijken met uid=0, $0 staat voor de gehele tekstregel.

    4. $ awk '/root|bert|kate/' /etc/passwd
      root:x:0:0:root:/root:/bin/bash
      bert:x:1000:1000:bert,,,:/home/bert:/bin/bash
      kate:x:1002:1002::/home/kate:/bin/sh

      Het voorbeeld spreekt voor zich ...

    5. $ awk 'BEGIN {printf "%.2f\n", 200.50 / 7}'
      28.64

      Een deling van reële getallen, bash kan dit niet zelf!!

  3. sed:

    sed wordt vooral gebruikt voor search and replace commando's. Alle volgende voorbeelden zijn variaties op dit thema. Bedenk dat sed data stuurt naar standaard output, en dat je dus een redirect nodig hebt om een file te creëren.
    Die nieuwe file kan niet de oude overschrijven.
    Je hebt dus meestal nog een mv commando nodig om de sed actie te vervolledigen.

    voorbeelden:

    1. $ cat /etc/passwd | sed 's/root/toor/g'
      toor:x:0:0:toor:/toor:/bin/bash
      daemon:x:1:1:daemon:/usr/sbin:/bin/sh
      bin:x:2:2:bin:/bin:/bin/sh
      sys:x:3:3:sys:/dev:/bin/sh


      De eenvoudige vervangtruuk.
      s is het commando voor sed: replace regular expression by replacement
      de regexp staat na de eerste slash, het replacement na de tweede slash en wordt afgesloten door de derde slash
      g staat voor vervang alle (anders wordt alleen de eerste van de regel vervangen)

    2. cat /etc/legal | sed 's/\ /\_/g'

      The_programs_included_with_the_Ubuntu_system_are_free_software;
      the_exact_distribution_terms_for_each_program_are_described_in_the
      individual_files_in_/usr/share/doc/*/copyright.
      Ubuntu_comes_with_ABSOLUTELY_NO_WARRANTY,_to_the_extent_permitted_by
      applicable_law.


      Vervangen van spaties door underscores. De spatie wordt in sed voorafgegaan door een \ want het is een speciaal teken, en zo ook de underscore. Het gevolg is dat dit commando nogal ascii-art achtig lijkt.

    3. for file in *
      do
      newfile=$(echo $file | sed 's/\ /\_/g')
      mv -v $file $newfile
      done


      Hopla is hier -> Hopla_is_hier
      Let it be - Beatles -> Let_it_be_-_Beatles
      Toy Story 3 -> Toy_Story_3


      Wie wil er geen komaf maken met spaties in filenamen ...

    4. $ echo "Deze tekst bevat paté, zurück en beëindigd" | sed -f raretekens.txt
      Deze tekst bevat paté, zurück en beëindigd

      raretekens.txt
      s/ë/\ë/g
      s/ï/\ï/g
      s/ä/\ä/g
      s/ü/\ü/g
      s/ö/\ö/g
      s/Ä/\Ä/g
      s/Ü/\Ü/g
      s/Ö/\Ö/g
      s/é/\é/g
      s/è/\è/g
      s/à/\à/g

      Een tekstfile omzetten naar html kan ook met sed. de file met de omzettingen moet je eerst samenstellen, en heet in ons geval raretekens.txt

  4. links:

    http://www.catonmat.net/sitemap/
    http://www.vectorsite.net/tsawk.html
    http://www.grymoire.com/Unix/Sed.html