summaryrefslogtreecommitdiff
path: root/awklib/eg/prog
diff options
context:
space:
mode:
Diffstat (limited to 'awklib/eg/prog')
-rw-r--r--awklib/eg/prog/alarm.awk81
-rw-r--r--awklib/eg/prog/awksed.awk31
-rw-r--r--awklib/eg/prog/cut.awk136
-rw-r--r--awklib/eg/prog/dupword.awk16
-rw-r--r--awklib/eg/prog/egrep.awk96
-rw-r--r--awklib/eg/prog/extract.awk72
-rw-r--r--awklib/eg/prog/histsort.awk14
-rw-r--r--awklib/eg/prog/id.awk69
-rw-r--r--awklib/eg/prog/igawk.sh130
-rw-r--r--awklib/eg/prog/labels.awk53
-rw-r--r--awklib/eg/prog/split.awk54
-rw-r--r--awklib/eg/prog/tee.awk38
-rw-r--r--awklib/eg/prog/translate.awk46
-rw-r--r--awklib/eg/prog/uniq.awk116
-rw-r--r--awklib/eg/prog/wc.awk68
-rw-r--r--awklib/eg/prog/wordfreq.awk13
16 files changed, 1033 insertions, 0 deletions
diff --git a/awklib/eg/prog/alarm.awk b/awklib/eg/prog/alarm.awk
new file mode 100644
index 00000000..fa42dce0
--- /dev/null
+++ b/awklib/eg/prog/alarm.awk
@@ -0,0 +1,81 @@
+# alarm --- set an alarm
+# Arnold Robbins, arnold@gnu.ai.mit.edu, Public Domain
+# May 1993
+
+# usage: alarm time [ "message" [ count [ delay ] ] ]
+
+BEGIN \
+{
+ # Initial argument sanity checking
+ usage1 = "usage: alarm time ['message' [count [delay]]]"
+ usage2 = sprintf("\t(%s) time ::= hh:mm", ARGV[1])
+
+ if (ARGC < 2) {
+ print usage > "/dev/stderr"
+ exit 1
+ } else if (ARGC == 5) {
+ delay = ARGV[4] + 0
+ count = ARGV[3] + 0
+ message = ARGV[2]
+ } else if (ARGC == 4) {
+ count = ARGV[3] + 0
+ message = ARGV[2]
+ } else if (ARGC == 3) {
+ message = ARGV[2]
+ } else if (ARGV[1] !~ /[0-9]?[0-9]:[0-9][0-9]/) {
+ print usage1 > "/dev/stderr"
+ print usage2 > "/dev/stderr"
+ exit 1
+ }
+
+ # set defaults for once we reach the desired time
+ if (delay == 0)
+ delay = 180 # 3 minutes
+ if (count == 0)
+ count = 5
+ if (message == "")
+ message = sprintf("\aIt is now %s!\a", ARGV[1])
+ else if (index(message, "\a") == 0)
+ message = "\a" message "\a"
+ # split up dest time
+ split(ARGV[1], atime, ":")
+ hour = atime[1] + 0 # force numeric
+ minute = atime[2] + 0 # force numeric
+
+ # get current broken down time
+ gettimeofday(now)
+
+ # if time given is 12-hour hours and it's after that
+ # hour, e.g., `alarm 5:30' at 9 a.m. means 5:30 p.m.,
+ # then add 12 to real hour
+ if (hour < 12 && now["hour"] > hour)
+ hour += 12
+
+ # set target time in seconds since midnight
+ target = (hour * 60 * 60) + (minute * 60)
+
+ # get current time in seconds since midnight
+ current = (now["hour"] * 60 * 60) + \
+ (now["minute"] * 60) + now["second"]
+
+ # how long to sleep for
+ naptime = target - current
+ if (naptime <= 0) {
+ print "time is in the past!" > "/dev/stderr"
+ exit 1
+ }
+ # zzzzzz..... go away if interrupted
+ if (system(sprintf("sleep %d", naptime)) != 0)
+ exit 1
+
+ # time to notify!
+ command = sprintf("sleep %d", delay)
+ for (i = 1; i <= count; i++) {
+ print message
+ # if sleep command interrupted, go away
+ if (system(command) != 0)
+ break
+ }
+
+ exit 0
+}
diff --git a/awklib/eg/prog/awksed.awk b/awklib/eg/prog/awksed.awk
new file mode 100644
index 00000000..cd96ddeb
--- /dev/null
+++ b/awklib/eg/prog/awksed.awk
@@ -0,0 +1,31 @@
+# awksed.awk --- do s/foo/bar/g using just print
+# Thanks to Michael Brennan for the idea
+
+# Arnold Robbins, arnold@gnu.ai.mit.edu, Public Domain
+# August 1995
+
+function usage()
+{
+ print "usage: awksed pat repl [files...]" > "/dev/stderr"
+ exit 1
+}
+
+BEGIN {
+ # validate arguments
+ if (ARGC < 3)
+ usage()
+
+ RS = ARGV[1]
+ ORS = ARGV[2]
+
+ # don't use arguments as files
+ ARGV[1] = ARGV[2] = ""
+}
+
+# look ma, no hands!
+{
+ if (RT == "")
+ printf "%s", $0
+ else
+ print
+}
diff --git a/awklib/eg/prog/cut.awk b/awklib/eg/prog/cut.awk
new file mode 100644
index 00000000..c69e6492
--- /dev/null
+++ b/awklib/eg/prog/cut.awk
@@ -0,0 +1,136 @@
+# cut.awk --- implement cut in awk
+# Arnold Robbins, arnold@gnu.ai.mit.edu, Public Domain
+# May 1993
+
+# Options:
+# -f list Cut fields
+# -d c Field delimiter character
+# -c list Cut characters
+#
+# -s Suppress lines without the delimiter character
+
+function usage( e1, e2)
+{
+ e1 = "usage: cut [-f list] [-d c] [-s] [files...]"
+ e2 = "usage: cut [-c list] [files...]"
+ print e1 > "/dev/stderr"
+ print e2 > "/dev/stderr"
+ exit 1
+}
+BEGIN \
+{
+ FS = "\t" # default
+ OFS = FS
+ while ((c = getopt(ARGC, ARGV, "sf:c:d:")) != -1) {
+ if (c == "f") {
+ by_fields = 1
+ fieldlist = Optarg
+ } else if (c == "c") {
+ by_chars = 1
+ fieldlist = Optarg
+ OFS = ""
+ } else if (c == "d") {
+ if (length(Optarg) > 1) {
+ printf("Using first character of %s" \
+ " for delimiter\n", Optarg) > "/dev/stderr"
+ Optarg = substr(Optarg, 1, 1)
+ }
+ FS = Optarg
+ OFS = FS
+ if (FS == " ") # defeat awk semantics
+ FS = "[ ]"
+ } else if (c == "s")
+ suppress++
+ else
+ usage()
+ }
+
+ for (i = 1; i < Optind; i++)
+ ARGV[i] = ""
+ if (by_fields && by_chars)
+ usage()
+
+ if (by_fields == 0 && by_chars == 0)
+ by_fields = 1 # default
+
+ if (fieldlist == "") {
+ print "cut: needs list for -c or -f" > "/dev/stderr"
+ exit 1
+ }
+
+ if (by_fields)
+ set_fieldlist()
+ else
+ set_charlist()
+}
+function set_fieldlist( n, m, i, j, k, f, g)
+{
+ n = split(fieldlist, f, ",")
+ j = 1 # index in flist
+ for (i = 1; i <= n; i++) {
+ if (index(f[i], "-") != 0) { # a range
+ m = split(f[i], g, "-")
+ if (m != 2 || g[1] >= g[2]) {
+ printf("bad field list: %s\n",
+ f[i]) > "/dev/stderr"
+ exit 1
+ }
+ for (k = g[1]; k <= g[2]; k++)
+ flist[j++] = k
+ } else
+ flist[j++] = f[i]
+ }
+ nfields = j - 1
+}
+function set_charlist( field, i, j, f, g, t,
+ filler, last, len)
+{
+ field = 1 # count total fields
+ n = split(fieldlist, f, ",")
+ j = 1 # index in flist
+ for (i = 1; i <= n; i++) {
+ if (index(f[i], "-") != 0) { # range
+ m = split(f[i], g, "-")
+ if (m != 2 || g[1] >= g[2]) {
+ printf(bad character list: %s\n",
+ f[i]) > "/dev/stderr"
+ exit 1
+ }
+ len = g[2] - g[1] + 1
+ if (g[1] > 1) # compute length of filler
+ filler = g[1] - last - 1
+ else
+ filler = 0
+ if (filler)
+ t[field++] = filler
+ t[field++] = len # length of field
+ last = g[2]
+ flist[j++] = field - 1
+ } else {
+ if (f[i] > 1)
+ filler = f[i] - last - 1
+ else
+ filler = 0
+ if (filler)
+ t[field++] = filler
+ t[field++] = 1
+ last = f[i]
+ flist[j++] = field - 1
+ }
+ }
+ FIELDWIDTHS = join(t, 1, field - 1)
+ nfields = j - 1
+}
+{
+ if (by_fields && suppress && $0 !~ FS)
+ next
+
+ for (i = 1; i <= nfields; i++) {
+ if ($flist[i] != "") {
+ printf "%s", $flist[i]
+ if (i < nfields && $flist[i+1] != "")
+ printf "%s", OFS
+ }
+ }
+ print ""
+}
diff --git a/awklib/eg/prog/dupword.awk b/awklib/eg/prog/dupword.awk
new file mode 100644
index 00000000..8ae0fdc7
--- /dev/null
+++ b/awklib/eg/prog/dupword.awk
@@ -0,0 +1,16 @@
+# dupword --- find duplicate words in text
+# Arnold Robbins, arnold@gnu.ai.mit.edu, Public Domain
+# December 1991
+
+{
+ $0 = tolower($0)
+ gsub(/[^A-Za-z0-9 \t]/, "");
+ if ($1 == prev)
+ printf("%s:%d: duplicate %s\n",
+ FILENAME, FNR, $1)
+ for (i = 2; i <= NF; i++)
+ if ($i == $(i-1))
+ printf("%s:%d: duplicate %s\n",
+ FILENAME, FNR, $i)
+ prev = $NF
+}
diff --git a/awklib/eg/prog/egrep.awk b/awklib/eg/prog/egrep.awk
new file mode 100644
index 00000000..5a5ec988
--- /dev/null
+++ b/awklib/eg/prog/egrep.awk
@@ -0,0 +1,96 @@
+# egrep.awk --- simulate egrep in awk
+# Arnold Robbins, arnold@gnu.ai.mit.edu, Public Domain
+# May 1993
+
+# Options:
+# -c count of lines
+# -s silent - use exit value
+# -v invert test, success if no match
+# -i ignore case
+# -l print filenames only
+# -e argument is pattern
+
+BEGIN {
+ while ((c = getopt(ARGC, ARGV, "ce:svil")) != -1) {
+ if (c == "c")
+ count_only++
+ else if (c == "s")
+ no_print++
+ else if (c == "v")
+ invert++
+ else if (c == "i")
+ IGNORECASE = 1
+ else if (c == "l")
+ filenames_only++
+ else if (c == "e")
+ pattern = Optarg
+ else
+ usage()
+ }
+ if (pattern == "")
+ pattern = ARGV[Optind++]
+
+ for (i = 1; i < Optind; i++)
+ ARGV[i] = ""
+ if (Optind >= ARGC) {
+ ARGV[1] = "-"
+ ARGC = 2
+ } else if (ARGC - Optind > 1)
+ do_filenames++
+
+# if (IGNORECASE)
+# pattern = tolower(pattern)
+}
+#{
+# if (IGNORECASE)
+# $0 = tolower($0)
+#}
+function beginfile(junk)
+{
+ fcount = 0
+}
+function endfile(file)
+{
+ if (! no_print && count_only)
+ if (do_filenames)
+ print file ":" fcount
+ else
+ print fcount
+
+ total += fcount
+}
+{
+ matches = ($0 ~ pattern)
+ if (invert)
+ matches = ! matches
+
+ fcount += matches # 1 or 0
+
+ if (! matches)
+ next
+
+ if (no_print && ! count_only)
+ nextfile
+
+ if (filenames_only && ! count_only) {
+ print FILENAME
+ nextfile
+ }
+
+ if (do_filenames && ! count_only)
+ print FILENAME ":" $0
+ else if (! count_only)
+ print
+}
+END \
+{
+ if (total == 0)
+ exit 1
+ exit 0
+}
+function usage( e)
+{
+ e = "Usage: egrep [-csvil] [-e pat] [files ...]"
+ print e > "/dev/stderr"
+ exit 1
+}
diff --git a/awklib/eg/prog/extract.awk b/awklib/eg/prog/extract.awk
new file mode 100644
index 00000000..a9f5b80f
--- /dev/null
+++ b/awklib/eg/prog/extract.awk
@@ -0,0 +1,72 @@
+# extract.awk --- extract files and run programs
+# from texinfo files
+# Arnold Robbins, arnold@gnu.ai.mit.edu, Public Domain
+# May 1993
+
+BEGIN { IGNORECASE = 1 }
+
+/^@c(omment)?[ \t]+system/ \
+{
+ if (NF < 3) {
+ e = (FILENAME ":" FNR)
+ e = (e ": badly formed `system' line")
+ print e > "/dev/stderr"
+ next
+ }
+ $1 = ""
+ $2 = ""
+ stat = system($0)
+ if (stat != 0) {
+ e = (FILENAME ":" FNR)
+ e = (e ": warning: system returned " stat)
+ print e > "/dev/stderr"
+ }
+}
+/^@c(omment)?[ \t]+file/ \
+{
+ if (NF != 3) {
+ e = (FILENAME ":" FNR ": badly formed `file' line")
+ print e > "/dev/stderr"
+ next
+ }
+ if ($3 != curfile) {
+ if (curfile != "")
+ close(curfile)
+ curfile = $3
+ }
+
+ for (;;) {
+ if ((getline line) <= 0)
+ unexpected_eof()
+ if (line ~ /^@c(omment)?[ \t]+endfile/)
+ break
+ else if (line ~ /^@(end[ \t]+)?group/)
+ continue
+ if (index(line, "@") == 0) {
+ print line > curfile
+ continue
+ }
+ n = split(line, a, "@")
+ # if a[1] == "", means leading @,
+ # don't add one back in.
+ for (i = 2; i <= n; i++) {
+ if (a[i] == "") { # was an @@
+ a[i] = "@"
+ if (a[i+1] == "")
+ i++
+ }
+ }
+ print join(a, 1, n, SUBSEP) > curfile
+ }
+}
+function unexpected_eof()
+{
+ printf("%s:%d: unexpected EOF or error\n", \
+ FILENAME, FNR) > "/dev/stderr"
+ exit 1
+}
+
+END {
+ if (curfile)
+ close(curfile)
+}
diff --git a/awklib/eg/prog/histsort.awk b/awklib/eg/prog/histsort.awk
new file mode 100644
index 00000000..c2c9d1a7
--- /dev/null
+++ b/awklib/eg/prog/histsort.awk
@@ -0,0 +1,14 @@
+# histsort.awk --- compact a shell history file
+# Arnold Robbins, arnold@gnu.ai.mit.edu, Public Domain
+# May 1993
+
+# Thanks to Byron Rakitzis for the general idea
+{
+ if (data[$0]++ == 0)
+ lines[++count] = $0
+}
+
+END {
+ for (i = 1; i <= count; i++)
+ print lines[i]
+}
diff --git a/awklib/eg/prog/id.awk b/awklib/eg/prog/id.awk
new file mode 100644
index 00000000..b29ef61a
--- /dev/null
+++ b/awklib/eg/prog/id.awk
@@ -0,0 +1,69 @@
+# id.awk --- implement id in awk
+# Arnold Robbins, arnold@gnu.ai.mit.edu, Public Domain
+# May 1993
+
+# output is:
+# uid=12(foo) euid=34(bar) gid=3(baz) \
+# egid=5(blat) groups=9(nine),2(two),1(one)
+
+BEGIN \
+{
+ if ((getline < "/dev/user") < 0) {
+ err = "id: no /dev/user support - cannot run"
+ print err > "/dev/stderr"
+ exit 1
+ }
+ close("/dev/user")
+
+ uid = $1
+ euid = $2
+ gid = $3
+ egid = $4
+
+ printf("uid=%d", uid)
+ pw = getpwuid(uid)
+ if (pw != "") {
+ split(pw, a, ":")
+ printf("(%s)", a[1])
+ }
+
+ if (euid != uid) {
+ printf(" euid=%d", euid)
+ pw = getpwuid(euid)
+ if (pw != "") {
+ split(pw, a, ":")
+ printf("(%s)", a[1])
+ }
+ }
+
+ printf(" gid=%d", gid)
+ pw = getgrgid(gid)
+ if (pw != "") {
+ split(pw, a, ":")
+ printf("(%s)", a[1])
+ }
+
+ if (egid != gid) {
+ printf(" egid=%d", egid)
+ pw = getgrgid(egid)
+ if (pw != "") {
+ split(pw, a, ":")
+ printf("(%s)", a[1])
+ }
+ }
+
+ if (NF > 4) {
+ printf(" groups=");
+ for (i = 5; i <= NF; i++) {
+ printf("%d", $i)
+ pw = getgrgid($i)
+ if (pw != "") {
+ split(pw, a, ":")
+ printf("(%s)", a[1])
+ }
+ if (i < NF)
+ printf(",")
+ }
+ }
+ print ""
+}
diff --git a/awklib/eg/prog/igawk.sh b/awklib/eg/prog/igawk.sh
new file mode 100644
index 00000000..a9fff180
--- /dev/null
+++ b/awklib/eg/prog/igawk.sh
@@ -0,0 +1,130 @@
+#! /bin/sh
+
+# igawk --- like gawk but do @include processing
+# Arnold Robbins, arnold@gnu.ai.mit.edu, Public Domain
+# July 1993
+
+if [ "$1" = debug ]
+then
+ set -x
+ shift
+else
+ # cleanup on exit, hangup, interrupt, quit, termination
+ trap 'rm -f /tmp/ig.[se].$$' 0 1 2 3 15
+fi
+
+while [ $# -ne 0 ] # loop over arguments
+do
+ case $1 in
+ --) shift; break;;
+
+ -W) shift
+ set -- -W"$@"
+ continue;;
+
+ -[vF]) opts="$opts $1 '$2'"
+ shift;;
+
+ -[vF]*) opts="$opts '$1'" ;;
+
+ -f) echo @include "$2" >> /tmp/ig.s.$$
+ shift;;
+
+ -f*) f=`echo "$1" | sed 's/-f//'`
+ echo @include "$f" >> /tmp/ig.s.$$ ;;
+
+ -?file=*) # -Wfile or --file
+ f=`echo "$1" | sed 's/-.file=//'`
+ echo @include "$f" >> /tmp/ig.s.$$ ;;
+
+ -?file) # get arg, $2
+ echo @include "$2" >> /tmp/ig.s.$$
+ shift;;
+
+ -?source=*) # -Wsource or --source
+ t=`echo "$1" | sed 's/-.source=//'`
+ echo "$t" >> /tmp/ig.s.$$ ;;
+
+ -?source) # get arg, $2
+ echo "$2" >> /tmp/ig.s.$$
+ shift;;
+
+ -?version)
+ echo igawk: version 1.0 1>&2
+ gawk --version
+ exit 0 ;;
+
+ -[W-]*) opts="$opts '$1'" ;;
+
+ *) break;;
+ esac
+ shift
+done
+
+if [ ! -s /tmp/ig.s.$$ ]
+then
+ if [ -z "$1" ]
+ then
+ echo igawk: no program! 1>&2
+ exit 1
+ else
+ echo "$1" > /tmp/ig.s.$$
+ shift
+ fi
+fi
+
+# at this point, /tmp/ig.s.$$ has the program
+gawk -- '
+# process @include directives
+
+function pathto(file, i, t, junk)
+{
+ if (index(file, "/") != 0)
+ return file
+
+ for (i = 1; i <= ndirs; i++) {
+ t = (pathlist[i] "/" file)
+ if ((getline junk < t) > 0) {
+ # found it
+ close(t)
+ return t
+ }
+ }
+ return ""
+}
+BEGIN {
+ path = ENVIRON["AWKPATH"]
+ ndirs = split(path, pathlist, ":")
+ for (i = 1; i <= ndirs; i++) {
+ if (pathlist[i] == "")
+ pathlist[i] = "."
+ }
+ stackptr = 0
+ input[stackptr] = ARGV[1] # ARGV[1] is first file
+
+ for (; stackptr >= 0; stackptr--) {
+ while ((getline < input[stackptr]) > 0) {
+ if (tolower($1) != "@include") {
+ print
+ continue
+ }
+ fpath = pathto($2)
+ if (fpath == "") {
+ printf("igawk:%s:%d: cannot find %s\n", \
+ input[stackptr], FNR, $2) > "/dev/stderr"
+ continue
+ }
+ if (! (fpath in processed)) {
+ processed[fpath] = input[stackptr]
+ input[++stackptr] = fpath
+ } else
+ print $2, "included in", input[stackptr], \
+ "already included in", \
+ processed[fpath] > "/dev/stderr"
+ }
+ close(input[stackptr])
+ }
+}' /tmp/ig.s.$$ > /tmp/ig.e.$$
+eval gawk -f /tmp/ig.e.$$ $opts -- "$@"
+
+exit $?
diff --git a/awklib/eg/prog/labels.awk b/awklib/eg/prog/labels.awk
new file mode 100644
index 00000000..55815d20
--- /dev/null
+++ b/awklib/eg/prog/labels.awk
@@ -0,0 +1,53 @@
+# labels.awk
+# Arnold Robbins, arnold@gnu.ai.mit.edu, Public Domain
+# June 1992
+
+# Program to print labels. Each label is 5 lines of data
+# that may have blank lines. The label sheets have 2
+# blank lines at the top and 2 at the bottom.
+
+BEGIN { RS = "" ; MAXLINES = 100 }
+
+function printpage( i, j)
+{
+ if (Nlines <= 0)
+ return
+
+ printf "\n\n" # header
+
+ for (i = 1; i <= Nlines; i += 10) {
+ if (i == 21 || i == 61)
+ print ""
+ for (j = 0; j < 5; j++) {
+ if (i + j > MAXLINES)
+ break
+ printf " %-41s %s\n", line[i+j], line[i+j+5]
+ }
+ print ""
+ }
+
+ printf "\n\n" # footer
+
+ for (i in line)
+ line[i] = ""
+}
+
+# main rule
+{
+ if (Count >= 20) {
+ printpage()
+ Count = 0
+ Nlines = 0
+ }
+ n = split($0, a, "\n")
+ for (i = 1; i <= n; i++)
+ line[++Nlines] = a[i]
+ for (; i <= 5; i++)
+ line[++Nlines] = ""
+ Count++
+}
+
+END \
+{
+ printpage()
+}
diff --git a/awklib/eg/prog/split.awk b/awklib/eg/prog/split.awk
new file mode 100644
index 00000000..e48653b4
--- /dev/null
+++ b/awklib/eg/prog/split.awk
@@ -0,0 +1,54 @@
+# split.awk --- do split in awk
+# Arnold Robbins, arnold@gnu.ai.mit.edu, Public Domain
+# May 1993
+
+# usage: split [-num] [file] [outname]
+
+BEGIN \
+{
+ outfile = "x" # default
+ count = 1000
+ if (ARGC > 4)
+ usage()
+
+ i = 1
+ if (ARGV[i] ~ /^-[0-9]+$/) {
+ count = -ARGV[i]
+ ARGV[i] = ""
+ i++
+ }
+ # test argv in case reading from stdin instead of file
+ if (i in ARGV)
+ i++ # skip data file name
+ if (i in ARGV) {
+ outfile = ARGV[i]
+ ARGV[i] = ""
+ }
+
+ s1 = s2 = "a"
+ out = (outfile s1 s2)
+}
+{
+ if (++tcount > count) {
+ close(out)
+ if (s2 == "z") {
+ if (s1 == "z") {
+ printf("split: %s is too large to split\n", \
+ FILENAME) > "/dev/stderr"
+ exit 1
+ }
+ s1 = chr(ord(s1) + 1)
+ s2 = "a"
+ } else
+ s2 = chr(ord(s2) + 1)
+ out = (outfile s1 s2)
+ tcount = 1
+ }
+ print > out
+}
+function usage( e)
+{
+ e = "usage: split [-num] [file] [outname]"
+ print e > "/dev/stderr"
+ exit 1
+}
diff --git a/awklib/eg/prog/tee.awk b/awklib/eg/prog/tee.awk
new file mode 100644
index 00000000..895e4398
--- /dev/null
+++ b/awklib/eg/prog/tee.awk
@@ -0,0 +1,38 @@
+# tee.awk --- tee in awk
+# Arnold Robbins, arnold@gnu.ai.mit.edu, Public Domain
+# May 1993
+# Revised December 1995
+
+BEGIN \
+{
+ for (i = 1; i < ARGC; i++)
+ copy[i] = ARGV[i]
+
+ if (ARGV[1] == "-a") {
+ append = 1
+ delete ARGV[1]
+ delete copy[1]
+ ARGC--
+ }
+ if (ARGC < 2) {
+ print "usage: tee [-a] file ..." > "/dev/stderr"
+ exit 1
+ }
+ ARGV[1] = "-"
+ ARGC = 2
+}
+{
+ # moving the if outside the loop makes it run faster
+ if (append)
+ for (i in copy)
+ print >> copy[i]
+ else
+ for (i in copy)
+ print > copy[i]
+ print
+}
+END \
+{
+ for (i in copy)
+ close(copy[i])
+}
diff --git a/awklib/eg/prog/translate.awk b/awklib/eg/prog/translate.awk
new file mode 100644
index 00000000..6e9aa5a5
--- /dev/null
+++ b/awklib/eg/prog/translate.awk
@@ -0,0 +1,46 @@
+# translate --- do tr like stuff
+# Arnold Robbins, arnold@gnu.ai.mit.edu, Public Domain
+# August 1989
+
+# bugs: does not handle things like: tr A-Z a-z, it has
+# to be spelled out. However, if `to' is shorter than `from',
+# the last character in `to' is used for the rest of `from'.
+
+function stranslate(from, to, target, lf, lt, t_ar, i, c)
+{
+ lf = length(from)
+ lt = length(to)
+ for (i = 1; i <= lt; i++)
+ t_ar[substr(from, i, 1)] = substr(to, i, 1)
+ if (lt < lf)
+ for (; i <= lf; i++)
+ t_ar[substr(from, i, 1)] = substr(to, lt, 1)
+ for (i = 1; i <= lf; i++) {
+ c = substr(from, i, 1)
+ if (index(target, c) > 0)
+ gsub(c, t_ar[c], target)
+ }
+ return target
+}
+
+function translate(from, to)
+{
+ return $0 = stranslate(from, to, $0)
+}
+
+# main program
+BEGIN {
+ if (ARGC < 3) {
+ print "usage: translate from to" > "/dev/stderr"
+ exit
+ }
+ FROM = ARGV[1]
+ TO = ARGV[2]
+ ARGC = 2
+ ARGV[1] = "-"
+}
+
+{
+ translate(FROM, TO)
+ print
+}
diff --git a/awklib/eg/prog/uniq.awk b/awklib/eg/prog/uniq.awk
new file mode 100644
index 00000000..5f63ef0f
--- /dev/null
+++ b/awklib/eg/prog/uniq.awk
@@ -0,0 +1,116 @@
+# uniq.awk --- do uniq in awk
+# Arnold Robbins, arnold@gnu.ai.mit.edu, Public Domain
+# May 1993
+
+function usage( e)
+{
+ e = "Usage: uniq [-udc [-n]] [+n] [ in [ out ]]"
+ print e > "/dev/stderr"
+ exit 1
+}
+
+# -c count lines. overrides -d and -u
+# -d only repeated lines
+# -u only non-repeated lines
+# -n skip n fields
+# +n skip n characters, skip fields first
+
+BEGIN \
+{
+ count = 1
+ outputfile = "/dev/stdout"
+ opts = "udc0:1:2:3:4:5:6:7:8:9:"
+ while ((c = getopt(ARGC, ARGV, opts)) != -1) {
+ if (c == "u")
+ non_repeated_only++
+ else if (c == "d")
+ repeated_only++
+ else if (c == "c")
+ do_count++
+ else if (index("0123456789", c) != 0) {
+ # getopt requires args to options
+ # this messes us up for things like -5
+ if (Optarg ~ /^[0-9]+$/)
+ fcount = (c Optarg) + 0
+ else {
+ fcount = c + 0
+ Optind--
+ }
+ } else
+ usage()
+ }
+
+ if (ARGV[Optind] ~ /^\+[0-9]+$/) {
+ charcount = substr(ARGV[Optind], 2) + 0
+ Optind++
+ }
+
+ for (i = 1; i < Optind; i++)
+ ARGV[i] = ""
+
+ if (repeated_only == 0 && non_repeated_only == 0)
+ repeated_only = non_repeated_only = 1
+
+ if (ARGC - Optind == 2) {
+ outputfile = ARGV[ARGC - 1]
+ ARGV[ARGC - 1] = ""
+ }
+}
+function are_equal( n, m, clast, cline, alast, aline)
+{
+ if (fcount == 0 && charcount == 0)
+ return (last == $0)
+
+ if (fcount > 0) {
+ n = split(last, alast)
+ m = split($0, aline)
+ clast = join(alast, fcount+1, n)
+ cline = join(aline, fcount+1, m)
+ } else {
+ clast = last
+ cline = $0
+ }
+ if (charcount) {
+ clast = substr(clast, charcount + 1)
+ cline = substr(cline, charcount + 1)
+ }
+
+ return (clast == cline)
+}
+NR == 1 {
+ last = $0
+ next
+}
+
+{
+ equal = are_equal()
+
+ if (do_count) { # overrides -d and -u
+ if (equal)
+ count++
+ else {
+ printf("%4d %s\n", count, last) > outputfile
+ last = $0
+ count = 1 # reset
+ }
+ next
+ }
+
+ if (equal)
+ count++
+ else {
+ if ((repeated_only && count > 1) ||
+ (non_repeated_only && count == 1))
+ print last > outputfile
+ last = $0
+ count = 1
+ }
+}
+
+END {
+ if (do_count)
+ printf("%4d %s\n", count, last) > outputfile
+ else if ((repeated_only && count > 1) ||
+ (non_repeated_only && count == 1))
+ print last > outputfile
+}
diff --git a/awklib/eg/prog/wc.awk b/awklib/eg/prog/wc.awk
new file mode 100644
index 00000000..e9898159
--- /dev/null
+++ b/awklib/eg/prog/wc.awk
@@ -0,0 +1,68 @@
+# wc.awk --- count lines, words, characters
+# Arnold Robbins, arnold@gnu.ai.mit.edu, Public Domain
+# May 1993
+
+# Options:
+# -l only count lines
+# -w only count words
+# -c only count characters
+#
+# Default is to count lines, words, characters
+
+BEGIN {
+ # let getopt print a message about
+ # invalid options. we ignore them
+ while ((c = getopt(ARGC, ARGV, "lwc")) != -1) {
+ if (c == "l")
+ do_lines = 1
+ else if (c == "w")
+ do_words = 1
+ else if (c == "c")
+ do_chars = 1
+ }
+ for (i = 1; i < Optind; i++)
+ ARGV[i] = ""
+
+ # if no options, do all
+ if (! do_lines && ! do_words && ! do_chars)
+ do_lines = do_words = do_chars = 1
+
+ print_total = (ARC - i > 2)
+}
+function beginfile(file)
+{
+ chars = lines = words = 0
+ fname = FILENAME
+}
+
+function endfile(file)
+{
+ tchars += chars
+ tlines += lines
+ twords += words
+ if (do_lines)
+ printf "\t%d", lines
+ if (do_words)
+ printf "\t%d", words
+ if (do_chars)
+ printf "\t%d", chars
+ printf "\t%s\n", fname
+}
+# do per line
+{
+ chars += length($0) + 1 # get newline
+ lines++
+ words += NF
+}
+
+END {
+ if (print_total) {
+ if (do_lines)
+ printf "\t%d", tlines
+ if (do_words)
+ printf "\t%d", twords
+ if (do_chars)
+ printf "\t%d", tchars
+ print "\ttotal"
+ }
+}
diff --git a/awklib/eg/prog/wordfreq.awk b/awklib/eg/prog/wordfreq.awk
new file mode 100644
index 00000000..b67fed47
--- /dev/null
+++ b/awklib/eg/prog/wordfreq.awk
@@ -0,0 +1,13 @@
+# Print list of word frequencies
+{
+ $0 = tolower($0) # remove case distinctions
+ gsub(/[^a-z0-9_ \t]/, "", $0) # remove punctuation
+ for (i = 1; i <= NF; i++)
+ freq[$i]++
+}
+END {
+ sort = "sort +1 -nr"
+ for (word in freq)
+ printf "%s\t%d\n", word, freq[word] | sort
+ close(sort)
+}