(g)awk in nutshell
LinuxDays 2018

Lukáš Bařinka
The AWK Programming Language - Book cover

Alfred V. Aho | Brian W. Kernighan | Peter J. Weinberger
AT&T Bell Laboratories (1977/1985)

AWK is a pattern-matching language
for writing short programs
to perform common data-manipulation tasks.

pattern { action }

pattern { action }

pattern { action }

...

  • White space as the default field separator
  • Implicit initializations
  • No type declarations for variables

Records and Fields

Records and Fields splitting

Patterns

cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
...
awk '' /etc/passwd
cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
...
awk '1' /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
...

awk -F: 'NR == 5' /etc/passwd
awk -F: 'NR <= 5' /etc/passwd
awk -F: 'NR >= 5 && NR <= 10 /etc/passwd
awk -F: 'NR % 2' /etc/passwd
awk -F: '/nologin/' /etc/passwd
awk -F: '!/nologin/' /etc/passwd
awk -F: '$4 < 10' /etc/passwd
awk -F: '$3 != $4' /etc/passwd
awk -F: '$1 ~ /es$/, $1 ~ /ews$/' /etc/passwd
awk -F: '$6 ~ "/" $1 "$"' /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
...

Actions

ls -l
total 12
-rw-r--r-- 1 barinkl barinkl   1 Oct  6  2018 a
-rw-r--r-- 1 barinkl barinkl  10 Oct  6  2018 b
-rw-r--r-- 1 barinkl barinkl 100 Oct  6  2018 c
... | awk '{ print NR ":",$5,$9 }'
1:
2: 1 a
3: 10 b
4: 100 c
... | awk 'NR>1 { print NR-1 ":",$5,$9 }' 
1: 1 a
2: 10 b
3: 100 c

ls -l
total 12
-rw-r--r-- 1 barinkl barinkl   1 Oct  6  2018 a
-rw-r--r-- 1 barinkl barinkl  10 Oct  6  2018 b
-rw-r--r-- 1 barinkl barinkl 100 Oct  6  2018 c
... | awk 'END { print NR }'
4
... | awk '/^-/ { c++ } END { print c }'
3
... | awk '{ sum+=$5 } END { print sum }'
111
... | awk '/^-/ { sum+=$5; c++ } END { print sum/c }' 
37
... | awk '/^-/ && $5>max { max=$5 } END { print max }' 
100

Example - Manual

man ls
LS(1)        User Commands       LS(1)

NAME
       ls - list directory contents

SYNOPSIS
       ls [OPTION]... [FILE]...

DESCRIPTION
       List   information   about  the
       FILEs (the current directory by
       default).   Sort entries alpha‐
       betically if none of  -cftuvSUX
       nor --sort is specified.

       Mandatory   arguments  to  long
       options are mandatory for short
       options too.

       -a, --all

man ls
LS(1)        User Commands       LS(1)

NAME
       ls - list directory contents

SYNOPSIS
       ls [OPTION]... [FILE]...

man ls | awk '$1'
LS(1)        User Commands       LS(1)
NAME
       ls - list directory contents
SYNOPSIS
       ls [OPTION]... [FILE]...
DESCRIPTION
       List   information   about  the
       FILEs (the current directory by
       default).   Sort entries alpha‐
       betically if none of  -cftuvSUX

man ls
LS(1)        User Commands       LS(1)

NAME
       ls - list directory contents

SYNOPSIS
       ls [OPTION]... [FILE]...

man ls | awk -F '[^[:alpha:]]' '$1'
LS(1)        User Commands       LS(1)
NAME
SYNOPSIS
DESCRIPTION
AUTHOR
REPORTING BUGS
COPYRIGHT
SEE ALSO
GNU coreutils August 2018        LS(1)

man ls
LS(1)        User Commands       LS(1)

NAME
       ls - list directory contents

SYNOPSIS
       ls [OPTION]... [FILE]...

man ls | ./sections
LS(1)        User Commands       LS(1)
NAME
SYNOPSIS
DESCRIPTION
AUTHOR
REPORTING BUGS
COPYRIGHT
SEE ALSO
GNU coreutils August 2018        LS(1)
#!/usr/bin/awk -f
BEGIN {
    FS="[^[:alpha:]]"
}

$1
man ls
LS(1)        User Commands       LS(1)

NAME
       ls - list directory contents

SYNOPSIS
       ls [OPTION]... [FILE]...

man ls | ./sections
23 LS(1)        User Commands       LS(1)
1 NAME
1 SYNOPSIS
1 DESCRIPTION
1 AUTHOR
2 REPORTING BUGS
1 COPYRIGHT
2 SEE ALSO
19 GNU coreutils August 2018        LS(1)
#!/usr/bin/awk -f
BEGIN {
    FS="[^[:alpha:]]"
}

$1 {
    print NF,$0
}
man ls
LS(1)        User Commands       LS(1)

NAME
       ls - list directory contents

SYNOPSIS
       ls [OPTION]... [FILE]...

man ls | ./sections
5 LS(1)        User Commands       LS(1)
1 NAME
1 SYNOPSIS
1 DESCRIPTION
1 AUTHOR
2 REPORTING BUGS
1 COPYRIGHT
2 SEE ALSO
5 GNU coreutils August 2018        LS(1)
#!/usr/bin/awk -f
BEGIN {
    FS="[^[:alpha:]]+"
}

$1 {
    print NF,$0
}
man ls
LS(1)        User Commands       LS(1)

NAME
       ls - list directory contents

SYNOPSIS
       ls [OPTION]... [FILE]...

man ls | ./sections
LS(1)        User Commands       LS(1)
NAME
SYNOPSIS
DESCRIPTION
AUTHOR
REPORTING BUGS
COPYRIGHT
SEE ALSO
GNU coreutils August 2018        LS(1)
380
#!/usr/bin/awk -f

BEGIN {
    FS="[^[:alpha:]]+"
}

$1

END { print NR }
man ls
LS(1)        User Commands       LS(1)

NAME
       ls - list directory contents

SYNOPSIS
       ls [OPTION]... [FILE]...

man ls | ./sections

LS(1)        User Commands       LS(1)
2
NAME
3
SYNOPSIS
3
...
GNU coreutils August 2018        LS(1)
9 380
#!/usr/bin/awk -f
BEGIN {
    FS="[^[:alpha:]]+"
}

$1 {
    print lines
    print $0
    chapters++
    lines=0
}

{
    lines++
}

END { print chapters,NR }
man ls
LS(1)        User Commands       LS(1)

NAME
       ls - list directory contents

SYNOPSIS
       ls [OPTION]... [FILE]...

man ls | ./sections
LS(1)        User Commands       LS(1)
2
NAME
3
SYNOPSIS
3
...
GNU coreutils August 2018        LS(1)
1
9 380
#!/usr/bin/awk -f
BEGIN {
    FS="[^[:alpha:]]+"
}

$1 {
   if (lines) print lines
   print $0
   chapters++
   lines=0
}

{
   lines++
}

END {
   if (lines) print lines
   print chapters,NR
}
man ls | ./sections
LS(1)        User Commands       LS(1)
2 4
NAME
3 5
SYNOPSIS
3 4
DESCRIPTION
341 936
AUTHOR
4 9
REPORTING BUGS
8 23
COPYRIGHT
11 43
SEE ALSO
7 21
GNU coreutils August 2018        LS(1)
1 4
9 380 1049
#!/usr/bin/awk -f
BEGIN {
   FS="[^[:alpha:]]+"
}

$1 {
   if (lines) print lines, words
   print $0
   chapters++
   t_words+=words
   lines=0
   words=0
}

{
   lines++
   for (i=1; i>=NF; i++)
      if ( $i!="" ) words++
}

END { 
   t_words+=words
   if (lines) print lines, words+0
   print chapters+0,NR,t_words+0
}
man ls | ./sections
LS(1)        User Commands       LS(1)
2 4 40
NAME
3 5 42
SYNOPSIS
3 4 42
DESCRIPTION
341 936 9179
AUTHOR
4 9 75
REPORTING BUGS
8 23 207
COPYRIGHT
11 43 338
SEE ALSO
7 21 183
GNU coreutils August 2018        LS(1)
1 4 39
9 380 1049 10145
#!/usr/bin/awk -f
BEGIN {
   FS="[^[:alpha:]]+"
}

$1 {
   if (lines)
     print lines, words, chars
   print $0
   chapters++
   t_words+=words
   t_chars+=chars
   lines=0
   words=0
   chars=0
}

{
   lines++
   for (i=1; i<=NF; i++)
      if ( $i!="" ) words++
   chars+=length+1
}

END { 
   t_words+=words
   t_chars+=chars
   if (lines)
      print lines, words, chars
   print chapters,NR,t_words,t_chars
}
man ls | ./sections
...
REPORTING BUGS
      8      23     207
COPYRIGHT
     11      43     338
SEE ALSO
      7      21     183
GNU coreutils August 2018        LS(1)
      1       4      39
      9     380    1049   10145

man ls | wc
    380     969   10145
#!/usr/bin/awk -f

function wc(l,w,c) {
   printf "%7d %7d %7d\n",l,w,c 
}

BEGIN {
   FS="[^[:alpha:]]+"
}

$1 {
   if (lines)
      wc(lines, words, chars)
   print $0
   chapters++
   t_words+=words
   t_chars+=chars
   lines=0
   words=0
   chars=0
}

{
   lines++
   for (i=1; i<=NF; i++)
      if ( $i!="" ) words++
   chars+=length+1
}

END { 
   t_words+=words
   t_chars+=chars
   if (lines)
      wc(lines, words, chars)
   printf "%7d ",chapters
   wc(NR,t_words,t_chars)
}
man ls | ./sections
LS(1)        User Commands       LS(1)
      2       4      40
NAME
      3       6      42
...
SEE ALSO
      7      15     183
GNU coreutils August 2018        LS(1)
      1       5      39
      9     380     969   10145

man ls | wc
    380     969   10145
#!/usr/bin/awk -f

function wc(l,w,c) {
   printf "%7d %7d %7d\n",l,w,c 
}

BEGIN {
   FS="[[:space:]]+"
}

$1 {
   if (lines)
      wc(lines, words, chars)
   print $0
   chapters++
   t_words+=words
   t_chars+=chars
   lines=0
   words=0
   chars=0
}

{
   lines++
   for (i=1; i<=NF; i++)
      if ( $i!="" ) words++
   chars+=length+1
}

END { 
   t_words+=words
   t_chars+=chars
   if (lines)
      wc(lines, words, chars)
   printf "%7d ",chapters
   wc(NR,t_words,t_chars)
}

awk and shell

A=12345
echo $A | awk '$A++'
12346

echo $A | awk '$A++'
echo $A | awk '$A++'
echo 12345 | awk '$A++'
echo 12345 | awk '$A++'
echo 12345 | awk '$0++'
echo 12345 | awk '$0++'
echo 12345 | awk '12345 { $0++; print $0 }'
echo 12345 | awk 'true { $0++; print $0 }'
echo 12345 | awk 'true { print $0 }'
echo 12345 | awk 'true { print 12346 }'
12346
W=80
awk 'length > width { print "Line",NR,"too long"}' file

awk 'length > 80 { print "Line",NR,"too long"}' file
awk 'length > '80' { print "Line",NR,"too long"}' file
awk 'length > '$W' { print "Line",NR,"too long"}' file
awk 'length > '"$W"' { print "Line",NR,"too long"}' file
awk 'length > '"$W"' { print "Line",NR,"too long"}' file

F=field
awk '$1 == "field" { print text ":" $0 }' file
awk '$1 == "'field'" { print text ":" $0 }' file
awk '$1 == "'$F'" { print text ":" $0 }' file
awk '$1 == "'"$F"'" { print text ":" $0 }' file
awk '$1 == "'"$F"'" { print text ":" $0 }' file
awk 'BEGIN { var="'"$X"'" }' file

awk 'script' var="$X" file

awk -v var="$X" 'script' file

awk 'BEGIN { var=ENVIRON["X"] }' file

Arrays

less logs/2009/01/08.log
...
Jan  8 00:43:01 ewait apache2: 1231371781 127.0.0.1 115 1405 "GET /server-status?auto HTTP/1.0"
Jan  8 00:43:57 ewait apache2: 1231371837 70.229.177.83 46 451 "GET /w00tw00t.at.ISC.SANS.DFind:) HTTP/1.1"
Jan  8 04:29:01 ewait apache2: 1231385341 127.0.0.1 115 1405 "GET /server-status?auto HTTP/1.0"
Jan  8 05:44:45 ewait apache2: 1231389885 89.207.232.190 168 1356 "GET /bin/msgimport HTTP/1.1"
Jan  8 05:44:45 ewait apache2: 1231389885 89.207.232.190 171 1356 "GET /rc/bin/msgimport HTTP/1.1"
Jan  8 05:44:45 ewait apache2: 1231389885 89.207.232.190 178 1356 "GET /roundcube/bin/msgimport HTTP/1.1"
Jan  8 05:49:01 ewait apache2: 1231390141 127.0.0.1 115 1405 "GET /server-status?auto HTTP/1.0"
Jan  8 06:16:39 ewait apache2: 1231391799 67.215.11.34 169 1356 "GET /nonexistenshit HTTP/1.1"
Jan  8 06:16:39 ewait apache2: 1231391799 67.215.11.34 173 1356 "GET /mail/bin/msgimport HTTP/1.1"
...
Screenshot of logfile processing
cat access_per_ip.awk
{ ip_in[$7] += $8; ip_out[$7] += $9; ip_count[$7]++ }

END {
   for (ip in ip_in) {
      sum_ip_count += ip_count[ip]
      sum_in += ip_in[ip]
      sum_out += ip_out[ip]
   }
   for (ip in ip_in)
      printf "%s %d %d %5.1f%% %5.1f%%\n",\
         ip, ip_count[ip], ip_out[ip],\
         100*ip_count[ip]/sum_ip_count,\
         100*ip_out[ip]/sum_out
}
awk -f access_per_ip.awk logs/2009/01/08.log | sort -k2n
127.0.0.1 1440 2023685  85.5%  68.1%
88.146.75.114 18 115625   1.1%   3.9%
67.205.76.148 12 16272   0.7%   0.5%
80.86.85.57 12 16272   0.7%   0.5%
...

PROCINFO["sorted_in"]="@val_num_desc"
for (ip in ip_count)
   printf "%s %d %d %5.1f%% %5.1f%%\n",...


awk -f access_per_ip.awk logs/2009/01/08.log

Input / Output

head /etc/passwd                                  wc -l *
root:x:0:0:root:/root:/bin/bash                        1 _
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin        1 a
bin:x:2:2:bin:/bin:/usr/sbin/nologin                   3 b
sys:x:3:3:sys:/dev:/usr/sbin/nologin                   1 c
sync:x:4:65534:sync:/bin:/bin/sync                     2 d
games:x:5:60:games:/usr/games:/usr/sbin/nologin      ... 
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin       10 s
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin           3 u
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin            1 w
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin     43 total

awk '{ print > substr($0,0,1) }' /etc/passwd
cat /etc/passwd
...
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
...
cat /etc/group
...
games:x:60:
nogroup:x:65534:
...


sync:x:4:nogroup:sync:/bin:/bin/sync
games:x:5:games:games:/usr/games:/usr/sbin/nologin
#!/usr/bin/awk -f
BEGIN {
   FS=":"
   OFS=FS
   while (getline < "/etc/group") {
      gname[$3] = $1                       gname[65534]="nogroup"
   }
}
                               sync:x:4:65534:sync:/bin:/bin/sync
{
   $4 = gname[$4]                        $4 = gname[65534]
   print                                 $4 = "nogroup"
}                            sync:x:4:nogroup:sync:/bin:/bin/sync

./grp /etc/passwd
#!/usr/bin/awk -f
BEGIN {
   server="wordnetweb.princeton.edu"
   connection="/inet/tcp/0/"server"/www"
   term=ARGV[1]
   url="/perl/webwn?s=" term
   request="GET " url " HTTP/1.0\r\n\r\n"
   start=0

   # send HTTP request
   print request |& connection
   # receive HTTP response
   while (connection |& getline) {
      print ++lines,go "::" $0 >> "/dev/stderr"
      # process data
      if ($0 ~ "<h3>") { go=1; gsub("^.*<h3>",""); 
         gsub("<[^>]*>",""); print; continue }
      if (go && $0 ~ "<li>" ) { gsub("<i>[:space:]*</i>","");
         gsub("<i>","\n    > "); gsub("<[^>]*>","");
         sub("S: \\(.\\) ",""); gsub(";","\n    >"); print "  *",$0 }
      if ($0 ~ "</ul>") { go=0; continue }
   }

   # close connection
   close(connection)
}
./word.awk linux 2>/dev/null
Noun
  * Linux (an open-source version of the UNIX operating system) 

./word.awk days 2>/dev/null
Noun
  * day, twenty-four hours, twenty-four hour period, 24-hour interval
    > "two days later they left"
    > "they put on two performances every day"
    > "there are 30,000 passengers per day"
  * day (some point or period in time) 
    > "it should arrive any day now"
    > "after that day she never trusted him again"
    > "those were the days"
    > "these days it is not unusual"

Real-life Examples

Unique Lines

awk '!x[$0]++'


a
c
b
a
c
d
       !x["a"]++

a                            x["a"]=  
c
b
a
c
d
       !false

a                            x["a"]= 
c
b
a
c
d
       true

a       a                    x["a"]=1
c
b
a
c
d
       !x["c"]++

a       a                    x["a"]=1
c                            x["c"]= 
b
a
c
d
       !false

a       a                    x["a"]=1
c                            x["c"]=
b
a
c
d
       true

a       a                    x["a"]=1
c       c                    x["c"]=1
b
a
c
d
       !x["b"]++

a       a                    x["a"]=1
c       c                    x["c"]=1
b                            x["b"]= 
a
c
d
       !false

a       a                    x["a"]=1
c       c                    x["c"]=1
b                            x["b"]=
a
c
d
       true

a       a                    x["a"]=1
c       c                    x["c"]=1
b       b                    x["b"]=1
a
c
d
       !x["a"]++

a       a                    x["a"]=1
c       c                    x["c"]=1
b       b                    x["b"]=1
a
c
d
       !true

a       a                    x["a"]=1
c       c                    x["c"]=1
b       b                    x["b"]=1
a
c
d
       false

a       a                    x["a"]=2
c       c                    x["c"]=1
b       b                    x["b"]=1
a 
c
d
       !x["c"]++

a       a                    x["a"]=2
c       c                    x["c"]=1
b       b                    x["b"]=1
a
c
d
       !true

a       a                    x["a"]=2
c       c                    x["c"]=1
b       b                    x["b"]=1
a
c
d
       false

a       a                    x["a"]=2
c       c                    x["c"]=2
b       b                    x["b"]=1
a
c
d
       !x["d"]++

a       a                    x["a"]=2
c       c                    x["c"]=2
b       b                    x["b"]=1
a                            x["d"]= 
c
d
       !false

a       a                    x["a"]=2
c       c                    x["c"]=2
b       b                    x["b"]=1
a                            x["d"]=
c
d
       true

a       a                    x["a"]=2
c       c                    x["c"]=2
b       b                    x["b"]=1
a                            x["d"]=1
c
d       d

Download Log

Download log plot
prev > $1 { sum += prev }
{ prev = $1 }
END { print sum+prev }

gPower


[08:17:58] core: state process
[08:17:58] core: I:  0.026 [0.176376] {L:S}
[08:17:58] core: U:  0.802 [0.41225-0.17644]
[08:17:58] core: T: 45.97 [1.151590]
[08:17:58] core: L: 1 [4.031919]
[08:17:58] core: heat off (tempH)
[08:17:58] core: O:  0.390 <0.1.0.0.0.0.0.1>
[08:17:58] core: state process
[08:17:58] core: I:  0.026 [0.176098] {L:S}
[08:17:59] core: U:  0.798 [0.40996-0.17617]
[08:17:59] core: T: 45.95 [1.151441]
[08:17:59] core: L: 1 [4.050195]
[08:17:59] core: heat off (tempH)
[08:17:59] core: O:  0.390 <0.1.0.0.0.0.1.0>
[08:17:59] core: state process
[08:17:59] core: I:  0.026 [0.176435] {L:S}
[08:17:59] core: U:  0.802 [0.41204-0.17637]
[08:18:00] core: T: 45.95 [1.151436]
[08:18:00] core: L: 1 [4.031209]
[08:18:00] core: heat off (tempH)
[08:18:00] core: O:  0.390 <0.1.0.0.0.0.0.1>
[08:18:00] core: state process
[08:18:00] core: I:  0.026 [0.176122] {L:S}
[08:18:00] core: U:  0.797 [0.40970-0.17632]
[08:18:00] core: T: 45.94 [1.151267]
[08:18:01] core: L: 1 [4.051915]
[08:18:01] core: P:  6.6 [0.012939]
[08:18:01] core: M: 1 [0.013354]
[08:18:01] core: heat off (tempH)
[08:18:01] core: O:  0.390 <0.1.0.0.0.0.1.0>
gPower data plot

[08:17:58] core: state process
[08:17:58] core: I:  0.026 [0.176376] {L:S}
[08:17:58] core: U:  0.802 [0.41225-0.17644]
[08:17:58] core: T: 45.97 [1.151590]
[08:17:58] core: L: 1 [4.031919]
[08:17:58] core: heat off (tempH)
[08:17:58] core: O:  0.390 <0.1.0.0.0.0.0.1>
[08:17:58] core: state process
[08:17:58] core: I:  0.026 [0.176098] {L:S}
[08:17:59] core: U:  0.798 [0.40996-0.17617]
[08:17:59] core: T: 45.95 [1.151441]
[08:17:59] core: L: 1 [4.050195]
[08:17:59] core: heat off (tempH)
[08:17:59] core: O:  0.390 <0.1.0.0.0.0.1.0>
[08:17:59] core: state process
[08:17:59] core: I:  0.026 [0.176435] {L:S}
[08:17:59] core: U:  0.802 [0.41204-0.17637]
[08:18:00] core: T: 45.95 [1.151436]
[08:18:00] core: L: 1 [4.031209]
[08:18:00] core: heat off (tempH)
[08:18:00] core: O:  0.390 <0.1.0.0.0.0.0.1>
[08:18:00] core: state process
[08:18:00] core: I:  0.026 [0.176122] {L:S}
[08:18:00] core: U:  0.797 [0.40970-0.17632]
[08:18:00] core: T: 45.94 [1.151267]
[08:18:01] core: L: 1 [4.051915]
[08:18:01] core: P:  6.6 [0.012939]
[08:18:01] core: M: 1 [0.013354]
[08:18:01] core: heat off (tempH)
[08:18:01] core: O:  0.390 <0.1.0.0.0.0.1.0>

   /U:/ { U = $4 }
   /heat on/ { H = 1 }
   /heat off/ { H = 0 }
   /T:/ { T = $4 }
   /I:/ { I = $4 }
   /O:/ { print $1,$4,U,I,T,H }

Software List

Software list screenshot
Software list sources
BEGIN {
   FS="/"
   basedir="/var/db/pkg"
   print "===== Software list ====="
   while ( "cd /var/db/pkg; ls -d */*" | getline ) {
      if ($1 != category) {
         category=$1
         print "\n==== " category " ===="
      }
      pkg($2)
   }
   print "\n --- //Generated: " strftime("%c") "//"
}
function pkg(info) {
   package=info
   sub("-[0-9].*","",package)
   version=info
   sub(package"-","",version)
   desc_file=basedir"/"$0"/DESCRIPTION"
   getline description < desc_file
   close(desc_file)
   web_file=basedir"/"$0"/HOMEPAGE"
   getline homepage < web_file
   close(web_file)
   gsub(" "," \\\\ ",homepage)
   print "  * **" package "** //(" version ")// \
          \\\\ " description " \\\\ " homepage
}

Comments into Texinfo

#!/bin/bash
### \about Knihovna %depend.sh% poskytuje funkci pro testování závislostí funkcí
### \about na globálních proměnných ve skriptech. Každá funkce, která používá
### \about globální proměnnou systému EDUX, by měla na začátku zavolat funkci %depend.sh:depend%
### \about z~této knihovny.
### \about
### \about Příkladem může být libovolná funkce, která používá např. proměnnou ''EDUXCONF''.
### \about
### \about Pokud není proměnná nezbytně nutná pro další běh programu, není nezbytné ji testovat
### \about funkcí %depend.sh:depend%.

### \brief Otestuje naplnění požadovaných proměnných.
### \param variable... seznam proměnných ke kontrole
### \return 0=OK, 1=KO, 3=InternalError
### \desc Postupně zkontroluje všechny zadané proměnné, zda obsahují nějakou hodnotu.
### \desc Pokud některá proměnná neexistuje nebo je prázdná, funkce skončí s chybou,
### \desc avšak program nekončí.

function depend { ... }
@node depend.sh
@chapter Knihovna depend.sh
@cindex depend.sh
   Knihovna @myref{depend.sh}{depend.sh} poskytuje funkci pro testování závislostí funkcí
   na globálních proměnných ve skriptech. Každá funkce, která používá   globální proměnnou
   systému EDUX, by měla na začátku zavolat funkci @myref{depend.sh:depend}{depend}
   z@tie{}této knihovny. @* @*    Příkladem může být libovolná funkce, která používá např.
   proměnnou @t{EDUXCONF}. @* @*    Pokud není proměnná nezbytně nutná pro další běh programu,
   není nezbytné ji testovat funkcí @myref{depend.sh:depend}{depend}.

@*

@node depend.sh:depend
@unnumberedsec Funkce depend
@cindex depend
   Postupně zkontroluje všechny zadané proměnné, zda obsahují nějakou hodnotu.
   ...

@exdent @sc{Použití}
@defun depend variable...
...
EDUX Documentation example
?

(g)awk in nutshell
LinuxDays 2018

Lukáš Bařinka