first draft

This commit is contained in:
cmccabe 2020-01-02 07:33:32 -05:00
parent 742a07a483
commit 6d0f3cb496
14 changed files with 505 additions and 0 deletions

34
00-intro.awk Executable file
View File

@ -0,0 +1,34 @@
#!/usr/bin/awk -f
# https://www.grymoire.com/Unix/Awk.html
# this is a hands-on awk tutorial. it was written loosely following
# the sequence in bruce barnett's awk tutorial, linked above. and it
# is designed that you can read and execute each script. these
# scripts are *not* the same scripts as in barnett's tutorial,
# although some may be similar.
# barnett's tutorial covers more material and in more detail, so you
# are encouraged to browse it if you want to learn more. this shell-
# based tutorial is designed as a quick start and to give you an idea
# of the essential features of awk.
# there are several versions of awk:
# nawk and gawk are probably the most common.
# this tutorial covers gawk alone, the gnu version of awk.
# read about other version of awk here, if interested:
# https://www.gnu.org/software/gawk/manual/html_node/Other-Versions.html
# ignore the code below for now. you'll learn what it means soon
# enough. but you can execute this script by running ./01.awk from
# the command line.
BEGIN {
print "This is a hands-on awk tutorial."
print "Read the file to start learning. Don't just run the script."
}
# each file in this tutorial is an executable awk script, although most
# are toyishly simple, just designed to demonstrate a specific feature
# of the language

30
01-essence-of-awk.awk Executable file
View File

@ -0,0 +1,30 @@
#!/usr/bin/awk -f
# https://www.grymoire.com/Unix/Awk.html
# awk (named for its creators aho, weinberger and kernighan) takes a a text
# file as input. the awk program then processes that file line by line.
# think of the awk program as performing some process for each line in the file.
# or, think of an awk program as a big loop in which you define how to process
# lines of input, one line per loop iteration.
# the simplest awk program has the following structure:
# PATTERN { ACTION }
# ...where PATTERN is a text pattern that is to be matched in each successive
# line of input, and ACTION is the code to execute if the match is successful.
# the simplest possible PATTERN to match is nothing. it matches everything.
# the following valid awk script will print each line that it matches, meaning
# that it will print everything. whatever file you pipe into it will be printed
# back, line by line.
{ print }
# an easy way to test this script is as follows (minus the greater-than sign):
# > ./01.awk /etc/passwd
# NOTE: see the shbang line? notice the "-f" after the awk filepath? that needs
# to be there if you're piping a text file into an awk script. by contrast, see
# script 00.awk which does not take a file as input and does not need the -f

34
02-script-structure.awk Executable file
View File

@ -0,0 +1,34 @@
#!/usr/bin/awk -f
# https://www.grymoire.com/Unix/Awk.html
# repeating for emphasis, awk moves line by line through the lines of
# an input file, processing each line in turn.
# but sometimes you want to do something first, before you start
# poring over the file, and maybe also something after you're done
# with the file. you can do these with BEGIN and END blocks.
# the script below will run exactly like the 01.awk script, except that
# it will print "BEGINNING OF THE SCRIPT" before processing all the
# lines of input, and "END OF THE SCRIPT" once the lines have all been
# processed.
BEGIN { print "BEGINNING OF THE SCRIPT" }
{ print }
END { print "END OF THE SCRIPT" }
# what are common use cases of the BEGIN and END blocks?
# BEGIN - awk is often used to generate data reports, and the BEGIN
# block is a good place to print a header row that will appear once
# before the data.
# the BEGIN block is also a good place to initialize variables and
# functions, as you'll learn about later (although functions can
# be defined anywhere, even outside of blocks).
# END - in reports, the END block is often where you will print
# summary statistics that were calculated in the main body of the
# script; or to generally do *something* with the results of the
# script.

26
03-field-separators.awk Executable file
View File

@ -0,0 +1,26 @@
#!/usr/bin/awk -f
# https://www.grymoire.com/Unix/Awk.html
# when awk reads a file line by line, it also provides you with
# variables representing the "fields" in each line.
# so, awk processes input line by line, but it makes it simple for you
# to process each line field by field, or to pick out any subset of
# fields that you want to crunch.
# by default, fields are words separated by whitespace, and they are
# represented by the variables $1, $2, $3 and so on.
# since we're practicing with /etc/password as the input file, whitepace
# separators won't work for us. fields in /etc/passwd are separated
# by colons. awk allows us to specify an alternate field separator
# by setting the FS variable.
# in this example, we'll change FS to a colon in the BEGIN block, and
# we will then print fields 1, 6 and 7 from each line of the input file.
# these are the username, their home directory path, and their shell.
BEGIN { FS=":" }
{ print $1, $6, $7 }

27
04-built-in-vars.awk Executable file
View File

@ -0,0 +1,27 @@
#!/usr/bin/awk -f
# https://www.grymoire.com/Unix/Awk.html
# built-in variables
# FS, OFS, NF, NR, RS, ORS, FILENAME
# barnett describes a number of other special variables, or environment
# variables as well:
# https://www.grymoire.com/Unix/Awk.html#toc-uh-55
# and even more predefined variables are listed and described in the
# gnu awk manual:
# https://www.gnu.org/software/gawk/manual/html_node/Built_002din-Variables.html#Built_002din-Variables
# example, the FILENAME variable. when reading data from a file (not
# from a pipe) FILENAME represents the name of the file providing input.
{ print FILENAME }
# must run script as './04.awk data.txt' not
# as cat data.txt ./04.awk'
# why is this useful? because awk can read from multiple files during one
# execution. you could run './04.awk data.txt data2.txt data3.txt', and
# the FILENAME variable will allow you to determine which file the script
# is processing at any given time during execution.

41
05-associative-arrays.awk Executable file
View File

@ -0,0 +1,41 @@
#!/usr/bin/awk -f
# https://www.grymoire.com/Unix/Awk.html
# associative arrays
# awk supports associative arrays, which are key=value pairs rather
# values indexed by sequences of numbers. you *can* use numbers to
# index your arrays, but it isn't required.
# an associative array:
# array["banana"] = 0
# array["grapes"] = 0
# array["durian"] = 0
# then you can perform an inventory count by incrementing each fruit's
# value when you see it listed in a file:
# array["banana"]++
# the following script creates an array called 'users' and with a new
# element for each username seen in the input. if a user is seen more
# than once, the value associated with that user is incremented.
# run this script with the 'w' command to get names of logged in users:
# w | ./05.awk
{
users[$1]++
}
END {
for (i in users) {
print i, users[i]
}
}
# note that there is a bug with this overly-simple script. the 'w'
# command contains two header rows that we would normally ignore.
# the bug is left here to maintain simplicity and to highlight the
# fact that you often have to address input issues like that in
# awk scripts.

34
06-output-formatting.awk Executable file
View File

@ -0,0 +1,34 @@
#!/usr/bin/awk -f
# https://www.grymoire.com/Unix/Awk.html
# printf for finer tuning of output formatting
# printf is just another print() function, but it gives you
# more control over the formatting of the string that is
# printed
# printf expects you to provide it with a lot more detail into
# how you want a string printed, even down to the character
# that terminates a line. print() by default will end a line
# with the ORS character, usually \n. printf() expects you
# to add your own line terminator wherever you want it.
# in the previous example, 05.awk, we printed out usernames
# and the number of login sessions they have open.
# in this example, let's use print to format that output so
# that it looks a little better.
{
users[$1]++
}
END {
for (i in users) {
printf("%-8s %2d\n", i, users[i])
}
}
# again, run this as w | ./06.awk

76
07-flow-control.awk Executable file
View File

@ -0,0 +1,76 @@
#!/usr/bin/awk -f
# https://www.grymoire.com/Unix/Awk.html
# user input, loops and flow control
# this example takes a few simple concepts and ties them
# together in a single demo
# 1. you can take user input in a script with the getline function
# like this:
# prompt "What is your name?"
# getline name < "-"
# print "Hello " name "!"
# 2. awk has flow control structures, that can be used in the following
# forms:
# for (var in array) { do something; }
# for (var=start_val; var>=end_val; var++) { do something; }
# while (var >= val) { do something; }
# do {do something} while (var >= val)
# switch (var) { case value/regexp: ...; default: ...; } [* see below]
# and the loops can be controlled with the following operators:
# break - exit the loop and continue with the rest of the program.
# continue = skip the rest of the current loop iteration, start next iteration.
# next = stop processing this record (not just loop), and move to next record.
# exit - exit the entire program, not just the loop.
# note that continue and next may be confusing because the nature of awk is that
# it loops over records. but next refers to the structural awk loop while
# continue refers to loops within the program that you have created in a for,
# while or do structure.
BEGIN {
print "This program will count how many times you type different fruit names."
fruit_count[""] = ""
while (1) {
print "Enter a fruit name, or type 'q' to quit."
getline fruit < "-"
if (fruit == "") {
print "You didn't enter a fruit name. Try again."
continue
} else if (fruit == "q" || fruit == "Q") {
exit
} else if (fruit == "done" || fruit == "DONE" || fruit == "Done") {
break
} else {
fruit_count[fruit]++
}
}
for (f in fruit_count) {
print f, fruit_count[f]
}
}
# in this example, we used the continue, break and exit within a while loop.
# this could have also used a for loop or a do loop in the BEGIN block.
# a more common form of flow control might be to use the 'next' statment in
# the main program block. as stated above, 'next' causes processing of the
# current line of input to stop and awk to read in the next line of input for
# processing.
# * the structure of the switch statement is like this:
# switch (expression) {
# case value or regular expression:
# case-body
# default:
# default-body
# }
# you can read more about the switch structure here:
# https://www.gnu.org/software/gawk/manual/html_node/Switch-Statement.html#Switch-Statement

30
08-math-functions.awk Executable file
View File

@ -0,0 +1,30 @@
#!/usr/bin/awk -f
# https://www.grymoire.com/Unix/Awk.html
# awk supports a number of mathematical and numerical functions.
# these won't be demonstrated in detail here because there are too
# many and their usage is fairly self-explanatory.
# there are basic mathematical operators:
# +, -, *, /
# math:
# exp, int, log, rand, srand, sqrt
# and
# trig functions:
# cos, sin, atan2,
# the example here will merely show how to validate that an input
# field is a number. use the regex: value ~ /^[0-9]*$/
BEGIN {
print "Enter a number:"
getline var < "-"
if (var ~ /^[0-9]*$/) {
print "The log of " var " is " log(var)
} else {
print var " isn't a number. What, are you trying to hack this system?"
}
}

29
09-string-functions.awk Executable file
View File

@ -0,0 +1,29 @@
#!/usr/bin/awk -f
# https://www.grymoire.com/Unix/Awk.html
# awk supports a number of functions for working with strings too.
# index(), length(), split(), substr(), tolower(), toupper(), strtonum()
# and more: https://www.grymoire.com/Unix/Awk.html#toc-uh-40
BEGIN {
print "Type a sentence with 7+ words:"
getline sentence < "-"
if (sentence == "") {
print "You're no fun."
} else {
print "Now type one word that was in your sentence:"
getline searchstr < "-"
if (searchstr == "") {
print "You're no fun."
} else {
pos = index(sentence, searchstr)
if (pos > 0) {
print searchstr " found at position " pos "."
} else {
print searchstr " not found."
}
}
}
}

30
10-misc-functions.awk Executable file
View File

@ -0,0 +1,30 @@
#!/usr/bin/awk -f
# https://www.grymoire.com/Unix/Awk.html
# the barnett awk guide lists a few other useful miscellaneous functions:
# system(), close(), systime(), and strftime()
# and the barnett guide demonstrates using getline to read from pipes,
# including looping through multiple lines of piped input from another
# command: https://www.grymoire.com/Unix/Awk.html#toc-uh-49
# system(command)
# ...run any arbitrary shell command, returning the exit code of
# whatever you ran.
# close() - used with getline when reading from pipes (see barnett)
# systime() - returns a timestamp as number of seconds since jan 1, 1970
# strftime(format_string, timestamp) - format date strings into
# human readable output
BEGIN {
now = systime()
print "The time is now " now "."
print "You might also know this as " strftime("%a %b %e %H:%M:%S %Z %Y" ,now)
}

27
11-user-def-functions.awk Executable file
View File

@ -0,0 +1,27 @@
#!/usr/bin/awk -f
# https://www.grymoire.com/Unix/Awk.html
# user defined functions
# very simple, functions are defined like this:
# function fname(arg) { do something }
# the function can be defined anywhere in the script, even at the
# end after all the BEGIN and END blocks, because awk reads the
# whole script before executing it.
BEGIN {
print "Enter a word:"
getline word < "-"
if (word == "") {
print "You're no fun."
} else {
repeatit(word)
}
}
function repeatit(w) {
print "You typed \"" w "\"."
print "Again, that was \"" w "\"."
}

15
12-further-reading.awk Normal file
View File

@ -0,0 +1,15 @@
#!/usr/bin/awk -f
# https://www.grymoire.com/Unix/Awk.html
# this tutorial has been designed as a quick start, only to give
# you the essential characteristics of awk and to show you how
# you can get started right away.
# you can go over bruce barnett's great tutorial, linked above,
# for more detail on the concepts covered here.
# you can also look into these other great resources:
#
# * https://www.gnu.org/software/gawk/manual/
# * (more soon)

72
data.text Normal file
View File

@ -0,0 +1,72 @@
dgoerger pts/1 139.162.170.123 Mon21 3:32m 0.24s 0.24s -bash
akrl pts/3 5.170.172.33 14:20 4:01 0.02s 0.00s emacsclient -c
ecelis pts/4 tmux(29990).%0 26Aug19 127days 0.02s 0.02s -bash
cerebro pts/5 189.39.0.145 Mon14 22:36m 0.06s 0.06s -bash
ecelis pts/6 tmux(29990).%1 04Oct19 88days 0.01s 0.01s -bash
nonlinea pts/7 tmux(2380).%0 20Sep19 101days 0.01s 0.01s -bash
nonlinea pts/8 tmux(2380).%1 20Sep19 101days 0.01s 0.01s -bash
slu pts/13 tmux(21498).%1 Fri14 3days 0.04s 0.04s -bash
milhan pts/14 tmux(29280).%0 24Dec19 7days 0.04s 0.02s links linfo.org
cel pts/18 tmux(10414).%4 24Dec19 6days 0.88s 0.61s vim libhttpd.c f
milhan pts/19 tmux(29280).%4 24Dec19 7days 0.03s 0.03s -bash
cel pts/20 tmux(10414).%0 24Dec19 6days 0.20s 0.20s -bash
gnsk pts/22 mosh- Fri06 4days 0.02s 9.08s mosh-server new -c 8 -s -l LANG=en_US.UTF-8 -l LANGUAGE=en_US:en
bacterio pts/24 tmux(24480).%0 24Dec19 29.00s 9:57 9:57 weechat
cmccabe pts/28 tmux(1164).%0 24Dec19 16:09 1:16 1:16 weechat
rgu pts/29 tmux(26989).%7 Fri20 3days 0.04s 0.04s -bash
bacterio pts/30 tmux(24480).%2 24Dec19 3:20m 0.48s 0.47s mutt
milhan pts/32 tmux(29280).%1 24Dec19 7days 0.04s 0.04s -bash
milhan pts/33 tmux(29280).%2 24Dec19 2days 0.15s 0.15s -bash
milhan pts/34 tmux(29280).%3 24Dec19 2days 0.39s 0.39s -bash
sj pts/36 205.166.94.5 24Dec19 2days 0.16s 0.16s /meta/s/sj/bin/ksh93u
milhan pts/37 tmux(29280).%5 24Dec19 7days 0.01s 0.00s less -s -M +Gg
niro pts/38 173.208.251.252 24Dec19 6days 0.38s 0.38s -bash
bacterio pts/40 tmux(24480).%7 Sat01 13:58m 0.02s 0.02s -bash
howellp pts/41 45.37.101.72 11:46 1:06m 0.08s 0.08s -bash
jkalb pts/42 148.75.212.87 12:38 1:59m 0.08s 0.05s ssh arpa.sdf.org
overland pts/43 tmux(13794).%0 Thu09 1:37m 2.02s 2.01s ssh overland@iceland.sdf.org
irnex pts/45 205.166.94.4 Mon18 19:52m 0.04s 0.04s -bash
palle pts/46 tmux(32126).%2 25Dec19 6days 0.02s 0.02s -bash
nydel pts/48 tmux(9695).%0 01:16 13:26m 0.02s 0.02s -bash
mjt pts/49 mosh- Fri17 3days 0.02s 0.05s mosh-server new -s -c 256 -l LANG=en_US.UTF-8
gnsk pts/50 mosh- Sun22 42:20m 0.02s 2.21s mosh-server new -c 8 -s -l LANG=en_US.UTF-8 -l LANGUAGE=en_US:en
cel pts/51 tmux(10414).%1 24Dec19 6days 0.44s 0.11s vi vault.php
cel pts/52 tmux(10414).%2 24Dec19 7days 0.07s 0.07s -bash
rgu pts/54 tmux(26989).%0 Thu09 5:41m 0.09s 0.09s -bash
spk pts/56 205.166.94.5 24Dec19 5:43m 0.97s 0.97s -zsh
roll1961 pts/58 92.41.118.25 Sat09 43:56m 0.10s 0.10s -bash
rgu pts/60 tmux(26989).%8 Fri20 3days 0.05s 0.05s -bash
cmccabe pts/61 108.48.69.254 12:39 5.00s 0.11s 0.03s w
jeschust pts/62 205.166.94.9 24Dec19 5days 0.03s 0.03s -bash
koenig pts/64 205.166.94.5 Wed18 21:52m 0.39s 0.39s -zsh
palle pts/65 tmux(32126).%0 25Dec19 6days 0.39s 2.19s tmux
ancrsprk pts/67 tmux(17990).%0 25Dec19 3:54m 1.20s 1.19s ssh iceland.freeshell.org
rgu pts/68 tmux(26989).%9 Fri20 3days 0.11s 0.11s -bash
ancrsprk pts/69 tmux(17990).%1 25Dec19 6days 0.01s 0.01s -bash
rgu pts/70 tmux(26989).%6 Thu09 1:50m 2.41s 2.41s ssh tty.freeshell.org
slu pts/71 tmux(21498).%0 25Dec19 27:54m 6.54s 6.53s mutt
palle pts/73 tmux(32126).%1 25Dec19 6days 13.15s 13.14s alpine
rgu pts/74 tmux(26989).%2 Thu09 4:10m 57.60s 57.60s weechat
rgu pts/75 tmux(26989).%3 Thu09 5:46m 0.04s 0.04s -bash
shriver pts/77 tmux(11433).%0 Wed19 5days 20.53s 20.53s -zsh
jubilo pts/79 :pts/104:S.0 Thu15 4days 0.62s 0.62s ssh -l bbs nest.wq5l.net
snowdusk pts/83 tmux(9749).%0 Thu18 12:59m 6.72s 6.67s ssh snowdusk@sverige.freeshell.org
bacterio pts/84 213.152.162.114- 14:35 29.00s 0.01s 0.00s tmux a -d
rgu pts/85 72.22.163.41 08:52 1:50m 0.02s 0.00s tmux attach -t 0
slu pts/89 mosh- 08:44 27:54m 0.05s 0.00s tmux attach
seanh pts/90 tmux(26153).%0 Thu10 2:51m 1:36 1:36 weechat
seanh pts/91 tmux(26153).%3 Thu10 5days 0.07s 0.04s nano weechat.txt
seanh pts/93 tmux(26153).%4 Thu10 2days 1.51s 1.45s ssh -t meta.sdf.org mutt
dgoerger pts/94 139.162.170.123 10:46 3:56m 0.07s 0.03s mutt -Rf mbox
seanh pts/95 tmux(26153).%5 Thu10 2:54m 0.75s 0.68s ssh -t meta.sdf.org bboard
seanh pts/96 tmux(26153).%6 Thu10 2:54m 2:19 2:19 newsboat
alenik pts/97 tmux(28411).%0 Thu11 2days 52.59s 52.18s irssi
barryjb pts/98 tmux(1288).%1 Mon14 23:49m 0.31s 0.29s vim test.c
jbaber pts/102 tmux(24008).%1 Mon20 17:44m 1.21s 1.13s vim csv_to_html.py
jubilo pts/104 71.218.234.20- 13:33 4days 0.92s 0.90s screen -S nest ssh -l bbs nest.wq5l.net
barryjb pts/108 tmux(1288).%2 Mon14 23:08m 0.07s 0.07s -bash
dgoerger pts/109 139.162.170.123 10:47 3:43m 0.03s 0.03s -bash
nydel pts/112 205.166.94.161- Mon19 13:26m 0.07s 0.00s tmux -l
overland pts/114 192.151.85.194 09:03 1:37m 0.01s 0.00s tmux attach
vulcanus pts/117 205.166.94.5 14:36 12.00s 0.03s 0.03s -bash
kd7jny pts/120 12.9.131.203 09:53 4:49m 0.01s 0.01s -bash