--- /dev/null
+# Misc
+*~
+*.swp
+
+# C output
+*.o
+*.a
+
+# Latex output
+*.aux
+*.log
+*.nav
+*.out
+*.snm
+*.toc
+*.vrb
--- /dev/null
+CFLAGS = -g -Wall -fPIC --std=gnu99
+CPPFLAGS = -I/usr/include/awk -I. -DHAVE_CONFIG_H
+
+test:Q: select.so
+ awk -f select.awk
+ #awk -f rhawk < testirc.txt
+ #awk -f rhawk < testirc.txt
+ #awk -f test.awk test.txt | awk -f rhawk #| grep 'points\|bid\|took'
+
+%.so: %.o
+ gcc $CFLAGS -shared -o $target $prereq $LDFLAGS
+
+%.o: %.c
+ gcc $CPPFLAGS $CFLAGS -c -o $target $prereq
--- /dev/null
+BEGIN {
+ extension("./select.so", "dlload");
+
+ nc0 = "netcat -l -p 12345"
+ nc1 = "netcat -l -p 54321"
+ stdin = "/dev/stdin"
+
+ while (1) {
+ # Open pipes
+ printf "" |& nc0
+ printf "" |& nc1
+
+ # Wait for input
+ if (!(fd = select("from", stdin, nc0, nc1))) {
+ print "timeout"
+ continue
+ }
+
+ # Read a line
+ if (fd == stdin)
+ if (!(st = getline line < fd))
+ exit 0
+ if (fd == nc0 || fd == nc1)
+ if (!(st = fd |& getline line)) {
+ print "broken pipe"
+ close(fd)
+ continue
+ }
+
+ # Print output
+ print "line: [" fd "] -> [" line "]"
+ }
+}
--- /dev/null
+/*
+ * select.c - Provide select functions for gawk.
+ */
+
+/*
+ * Copyright (C) 2012 Andy Spencer
+ *
+ * GAWK is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GAWK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "awk.h"
+
+int plugin_is_GPL_compatible;
+
+/* Select function:
+ * select(how, [timeout,] fd, ..)
+ * type = {to,from,error,any} */
+static NODE *do_select(int nargs)
+{
+ /* Parse arguments */
+ if (do_lint && get_curfunc_arg_count() < 2)
+ lintwarn("select: not enough arguments");
+
+ /* - check how */
+ int read = 0, write = 0, except = 0;
+ NODE *node = get_scalar_argument(0, FALSE);
+ NODE *how = force_string(node);
+ if (!strcmp("to", how->stptr)) write = 1;
+ if (!strcmp("from", how->stptr)) read = 1;
+ if (!strcmp("error", how->stptr)) except = 1;
+ if (!strcmp("any", how->stptr)) read = write = except = 1;
+ if (!read && !write && !except) {
+ printf("select: invalid select type: %.*s\n",
+ how->stlen, how->stptr);
+ return make_number((AWKNUM) -EINVAL);
+ }
+
+ /* - check timeout */
+ int first = 1;
+ struct timeval _timeout = {.tv_sec = 1, .tv_usec = 0};
+ struct timeval *timeout = &_timeout;
+ NODE *next = get_scalar_argument(1, FALSE);
+ if (next->type == Node_val && next->flags & NUMBER) {
+ AWKNUM num = force_number(next);
+ if (num < 0) {
+ timeout = NULL;
+ } else {
+ _timeout.tv_sec = (int)num;
+ _timeout.tv_usec = (num - (int)num) * 1E6;
+ printf("timeout -> %lf %ld,%ld\n", num,
+ _timeout.tv_sec,
+ _timeout.tv_usec);
+ }
+ first = 2;
+ }
+
+ /* Clear fds */
+ int nfds = 0;
+ fd_set readfds, writefds, exceptfds;
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+ FD_ZERO(&exceptfds);
+
+ /* Set fds */
+ for (int i = first; i < nargs; i++) {
+ NODE *node = get_scalar_argument(i, TRUE);
+ if (node == NULL)
+ continue;
+ NODE *str = force_string(node);
+ struct redirect *redir =
+ getredirect(str->stptr, str->stlen);
+ if (redir == NULL) {
+ int err = 0;
+ int type = read && write ? redirect_twoway :
+ read ? redirect_input :
+ write ? redirect_output : 0 ;
+ redir = redirect(str, type, &err);
+ }
+ if (redir == NULL) {
+ lintwarn("select: arg %d is not a redirect", i);
+ continue;
+ }
+ if ((read || except) && redir->iop->fd >= 0) {
+ int fd = redir->iop->fd;
+ if (read) FD_SET(fd, &readfds);
+ if (except) FD_SET(fd, &exceptfds);
+ if (fd > nfds) nfds = fd;
+ }
+ if ((write || except) && redir->fp) {
+ int fd = fileno(redir->fp);
+ if (write) FD_SET(fd, &writefds);
+ if (except) FD_SET(fd, &exceptfds);
+ if (fd > nfds) nfds = fd;
+ }
+ }
+
+ /* Select fds */
+ int rval = select(nfds+1, &readfds, &writefds, &exceptfds, timeout);
+ if (rval == 0)
+ return make_number((AWKNUM) 0);
+ if (rval == -1)
+ return make_number((AWKNUM) 0);
+
+ /* Return */
+ for (int i = first; i < nargs; i++) {
+ NODE *node = get_scalar_argument(i, TRUE);
+ if (node == NULL)
+ continue;
+ NODE *str = force_string(node);
+ struct redirect *redir =
+ getredirect(str->stptr, str->stlen);
+ if (redir == NULL)
+ continue;
+ if ((read || except) && redir->iop->fd >= 0) {
+ int fd = redir->iop->fd;
+ if ((read && FD_ISSET(fd, &readfds)) ||
+ (except && FD_ISSET(fd, &writefds)))
+ return node;
+ }
+ if ((write || except) && redir->fp) {
+ int fd = fileno(redir->fp);
+ if ((write && FD_ISSET(fd, &writefds)) ||
+ (except && FD_ISSET(fd, &exceptfds)))
+ return node;
+ }
+ }
+
+ /* Error */
+ return make_number((AWKNUM) 0);
+}
+
+/* Load select function */
+NODE *dlload(NODE *tree, void *dl)
+{
+ make_builtin("select", do_select, 99);
+ return make_number((AWKNUM) 0);
+}
--- /dev/null
+\documentclass{beamer}
+
+%%%%%%%%%%%%%%%%%%%
+% Commands/macros %
+%%%%%%%%%%%%%%%%%%%
+\newcommand{\link}[1]{
+ \begin{flushright}
+ \scriptsize{#1}
+ \end{flushright}
+}
+
+%%%%%%%%%%%%%%%%
+% Header/theme %
+%%%%%%%%%%%%%%%%
+%\usetheme[
+% pageofpages=of,
+% alternativetitlepage=true,
+%]{Torino}
+%\setbeamertemplate{footline}{}
+\setbeamersize{text margin left=20mm}
+\setbeamersize{text margin right=10mm}
+
+% Import packages
+\usepackage[english]{babel}
+\usepackage[latin1]{inputenc}
+\usepackage{times}
+\usepackage[T1]{fontenc}
+\usepackage{graphics}
+\usepackage{hyperref}
+\usepackage{ulem}
+\usepackage{listings}
+
+%%%%%%%%%%%%%%%%%%%%
+% Title page setup %
+%%%%%%%%%%%%%%%%%%%%
+\subject{%
+ sed,
+ awk
+}
+
+\keywords{%
+ sed,
+ awk,
+ grep,
+ unix,
+}
+
+\title[Sed and Awk]{%
+ Introduction to Sed and Awk scripting
+}
+
+\author[Spencer]{%
+ Andy Spencer
+}
+
+\date[2013-02-02]{%
+ February 2, 2013 \\
+ \small{San Fernando Valley Linux Users Group}
+}
+
+%%%%%%%%%%%%%%%%%
+% Content pages %
+%%%%%%%%%%%%%%%%%
+% Structure:
+% - intro
+% - perl/python
+% - gnu tools only
+% - history
+% - ed
+% - grep
+% - tr
+% - regular expressions
+% - sed
+% - sample command (s/foo/bar/)
+% - command structure
+% - other commands
+% - addresses and ranges
+% - branching
+% - the hold space
+% - fizz buzz
+% - awk
+% - sample command
+% - hello world
+% - sum
+% - average
+% - command structure
+% - patterns
+% - actions
+% - record and fields
+% - command line arguments
+% - awk quirks (default values, string concat)
+% - vpaste examples
+% - get_param
+% - cut_file
+% - stat
+% - head
+% - beer
+% - cowlife
+% - programming language
+% - variables, arrays
+% - statements
+% - operators
+% - builtin functions
+% - string manipulation
+% - file/command I/O, networking
+% - function definition
+% - local variables
+% - GNU extensions
+
+\begin{document}
+
+%%%%%%%%%%%%%%%%
+% Introduction %
+%%%%%%%%%%%%%%%%
+
+% intro
+% - perl/python
+% - gnu tools only
+% history
+% - ed
+% - grep
+% - tr
+% - regular expressions
+
+\begin{frame}[plain]
+ \titlepage
+\end{frame}
+
+\section{Introduction}
+\begin{frame}
+ \begin{quote}
+ One tool for one job?
+ \end{quote}
+ \begin{quote}
+ Those days are dead and gone and the eulogy was delivered by \sout{Perl}
+ \textrm{Python}.'' -Rob Pike
+ \end{quote}
+\end{frame}
+
+\begin{frame}[fragile]{When to use sed and awk?}
+ When to use sed?
+ \begin{itemize}
+ \item When you are ``editing'' a file
+ \item Short programs 1-5 lines
+ \end{itemize}
+ \ \par
+ When to use awk?
+ \begin{itemize}
+ \item When you need to ``summarize'' a file
+ \item Slightly longer programs 5-50 lines
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{When not to use them?}
+ \begin{itemize}
+ \item For longer program, use a programming language
+ \begin{itemize}
+ \item Awk lacks type checking, etc
+ \end{itemize}
+ \item For some very simple things
+ \begin{itemize}
+ \item grep, tr, seq
+ \item Unix shell expansion \$\{var/from/to\}
+ \item Fancy editor commands (vim, emacs)
+ \end{itemize}
+ \end{itemize}
+\end{frame}
+
+%\begin{frame}[fragile]{History}
+%\end{frame}
+
+
+%%%%%%%%%%%%%%%
+% Sed Sed Sed %
+%%%%%%%%%%%%%%%
+
+% - sample command (s/foo/bar/)
+% - command structure
+% - other commands
+% - addresses and ranges
+% - branching
+% - the hold space
+% - fizz buzz
+
+\begin{frame}[fragile]{Sed - simple commands}
+ Example
+\end{frame}
+
+\begin{frame}[fragile]{commands}
+ \begin{itemize}
+ \item[s] regular expression find/replace
+ \item[y] translate characters (like tr)
+ \item[p, P] print out the current line
+ \item[i, a] insert or append text
+ \item[c] change line
+ \item[n, N] read the next line of input
+ \item[q, Q] exit/quit
+ \item[r, R, w, W] read/write files
+ \item[b, t, T] branch to label
+ \item[d, D] delete pattern space
+ \item[h, H, g, G, x] work with the pattern and hold spaces
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{addresses and ranges}
+ \begin{itemize}
+ \item[number] match a line number
+ \item[\$] the last line
+ \item[/rege/] match a regular expression (not the same as s///)
+ \item[first~step] match every step'th line starting with first
+ \item[0,addr] match every step'th line starting with first
+ \item[addr,+N] address addr and N following lines
+ \item[addr,~N] match addr and lines up to a multiple of N
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{branching}
+ \begin{itemize}
+ \item Can be used for loops
+ \item Skipping when a pattern fails
+ \item I rarely use these
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{the hold space}
+ \begin{itemize}
+ \item Can be used for loops
+ \item Skipping when a pattern fails
+ \item Can be used like a variable
+ \item Also rarely used
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{fizz buzz}
+ Example
+\end{frame}
+
+%%%%%%%%%%%%%%%
+% Awk Awk Awk %
+%%%%%%%%%%%%%%%
+
+% sample command
+% - hello world
+% - sum
+% - average
+% command structure
+% - patterns
+% - actions
+% record and fields
+% command line arguments
+% awk quirks (default values, string concat)
+% vpaste examples
+% - get_param
+% - cut_file
+% - stat
+% - head
+% - beer
+% - cowlife
+% programming language
+% - variables, arrays
+% - statements
+% - operators
+% - builtin functions
+% - string manipulation
+% - file/command I/O, networking
+% - function definition
+% - local variables
+% - GNU extensions
+
+\begin{frame}[fragile]{Awk - simple commands}
+ Example
+\end{frame}
+
+\begin{frame}[fragile]{Command structure}
+ Basic awk scripts consist of patterns and actions
+
+ When a pattern matches, the action is executed
+
+ Some special patterns: BEGIN, END, BEGINFILE, ENDFILE
+ \begin{lstlisting}
+ PATTERN { ACTION }
+ PATTERN { ACTION }
+ \end{lstlisting}
+\end{frame}
+
+\begin{frame}[fragile]{Records and fields}
+ Text is split twice when reading the file
+
+ Patterns are matched against records
+
+ Fields can be accessed using \$N
+
+ \
+ \par
+ \begin{itemize}
+ \item[Records] by default, a line, changed using RS
+ \item[Fields] by default, a word ina line, changed using FS
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{Command line arguments}
+ \begin{itemize}
+ \item[-v] Set a variable (var=val)
+ \item[-F] Change field separator, can also be done from BEGIN
+ \end{itemize}
+ \begin{lstlisting}
+ awk -v 'var=$VAR' '{ script }
+ \end{lstlisting}
+\end{frame}
+
+\begin{frame}[fragile]{Awk quirks}
+ \begin{itemize}
+ \item default values are 0, no need for declaration
+ \item string concatonation is implicit
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{vpaste examples - get param}
+ Example
+\end{frame}
+
+\begin{frame}[fragile]{vpaste examples - cut file}
+ Example
+\end{frame}
+
+\begin{frame}[fragile]{vpaste examples - stat}
+ Example
+\end{frame}
+
+\begin{frame}[fragile]{vpaste examples - head}
+ Example
+\end{frame}
+
+\begin{frame}[fragile]{vpaste examples - cowlife}
+ Example
+\end{frame}
+
+\begin{frame}[fragile]{awk as a programming language}
+ \begin{itemize}
+ \item built-in functions
+ \item user defined functions
+ \item variables
+ \item file i/o
+ \item networking
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{Variables and arrays}
+\end{frame}
+
+\begin{frame}[fragile]{Statements}
+ \begin{itemize}
+ \item if (condition) body [ else body ]
+ \item while (condition) body
+ \item for (i=0; i<10; i++) body
+ \item for (i in array) body
+ \item break, continue
+ \item delete var, delete array[index]
+ \item swtich (expr) { case value: body; default: body }
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{Builtin functions}
+ \begin{itemize}
+ \item[Math] atan2, cos, exp, int, log, rand, sin, sqrt, srand
+ \item[Strings] asort, gsub, length, match, split, sprintf
+ \item[Time] mktime, strftime, systime
+ \item[Bitwise] add, or, xor, etc
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{I/O and networking}
+ \begin{itemize}
+ \item next, nextfile, print, printf
+ \item system, fflush
+ \end{itemize}
+ Reading from files and commands
+ \begin{itemize}
+ \item getline [var] [<file]
+ \item command | getline [var]
+ \item command |\& getline [var]
+ \end{itemize}
+ Writing to files and commands
+ \begin{itemize}
+ \item print .. > > file
+ \item print .. | command
+ \item print .. |\& command
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{User defined functions}
+ \begin{lstlisting}
+ function sayhi(name, str) {
+ str = "Hello, " name "!'
+ print str
+ }
+ \end{lstlisting}
+\end{frame}
+
+\begin{frame}[fragile]{GNU extensions}
+ Example
+\end{frame}
+
+\end{document}
--- /dev/null
+#!/bin/bash
+
+awk 'BEGIN { print "Hello, world" }'
--- /dev/null
+#!/bin/awk -f
+BEGIN { RS="[^0-9eE.+-]" }
+// { sum += $0 }
+END { print sum }
--- /dev/null
+#!/bin/awk -f
+BEGIN { RS="[^0-9eE.+-]+" }
+/[0-9]/ { sum += $0; cnt++ }
+END { print sum / cnt }
--- /dev/null
+#!/bin/bash
+
+frame="
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . . . # . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . # . # . . . . . . . . . . . .
+. . . . . . . . . . . . . # # . . . . . . # # . . . . . . . . . . . . # # .
+. . . . . . . . . . . . # . . . # . . . . # # . . . . . . . . . . . . # # .
+. # # . . . . . . . . # . . . . . # . . . # # . . . . . . . . . . . . . . .
+. # # . . . . . . . . # . . . # . # # . . . . # . # . . . . . . . . . . . .
+. . . . . . . . . . . # . . . . . # . . . . . . . # . . . . . . . . . . . .
+. . . . . . . . . . . . # . . . # . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . # # . . . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+"
+
+while sleep 0.05; do
+ echo "$frame" | cowsay -n
+ frame=$(echo "$frame" | awk '
+ function count(i) {
+ cnt = 0;
+ if (tops[i-1] == "#") cnt++;
+ if (tops[i ] == "#") cnt++;
+ if (tops[i+1] == "#") cnt++;
+
+ if (curs[i-1] == "#") cnt++;
+ if (curs[i+1] == "#") cnt++;
+
+ if (bots[i-1] == "#") cnt++;
+ if (bots[i ] == "#") cnt++;
+ if (bots[i+1] == "#") cnt++;
+ return cnt;
+ }
+
+ function run() {
+ split(top, tops, " ")
+ split(cur, curs, " ")
+ split(bot, bots, " ")
+ len = length(curs);
+ for (i=1; i < len+1; i++) {
+ new = curs[i]
+ cnt = count(i)
+ if (cnt < 2) new = ".";
+ if (cnt == 3) new = "#";
+ if (cnt > 3) new = ".";
+ printf "%s%s", new, i==len ? "" : " "
+ }
+ print ""
+ }
+
+ // {
+ top=cur; cur=bot; bot=$0
+ if (cur) run()
+ }
+
+ END {
+ top=cur; cur=bot; bot="";
+ run();
+ }
+ ')
+done
--- /dev/null
+#!/bin/bash
+
+# cut file
+bnd="${CONTENT_TYPE/*boundary\=/}"
+
+awk -v "want=$1" -v "bnd=$bnd" '
+ BEGIN { RS="\r\n" }
+
+ # reset based on boundaries
+ $0 == "--"bnd"" { st=1; next; }
+ $0 == "--"bnd"--" { st=0; next; }
+ $0 == "--"bnd"--\r" { st=0; next; }
+
+ # search for wanted file
+ st == 1 && $0 ~ "^Content-Disposition:.* name=\""want"\"" { st=2; next; }
+ st == 1 && $0 == "" { st=9; next; }
+
+ # wait for newline, then start printing
+ st == 2 && $0 == "" { st=3; next; }
+ st == 3 { print $0 }
+ # head
+' | head -c $((128*1024)) # Limit size to 128K
--- /dev/null
+#!/bin/bash
+
+# get param
+awk -v "key=member" '
+ BEGIN {RS=" "; FS="="}
+ $1 ~ key {print $2}
+' <<-EOF
+ name=andy member=sfvlug
+EOF
--- /dev/null
+#!/bin/bash
+
+# List
+awk -v 'rows=4' -v 'cols=60' '
+ FNR==1 { gsub(/.*\//, "", FILENAME);
+ print FILENAME
+ print "-----" }
+ FNR==1,/^$/ { next }
+ /\S/ { i++; printf "%."cols"s\n", $0 }
+ i>=rows { nextfile }
+ ENDFILE { i=0; print "" }
+' $(ls -t db/*)
--- /dev/null
+#!/bin/bash
+
+# Stat
+ls -l --time-style='+%Y %m' db |
+awk -v 'hdr=Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec' '
+ BEGIN { printf "%64s\n", hdr }
+ NR>1 { cnt[$6+0][$7+0]++ }
+ END { for (y in cnt) {
+ printf "%4d", y
+ for (m=1; m<=12; m++)
+ printf "%5s", cnt[y][m]
+ printf "\n" } }'
--- /dev/null
+#!/bin/awk -f
+
+function connect(method)
+{
+ HOST = "ctf.nullcon.net"
+ FILE = "/inet/tcp/0/" HOST "/80"
+ PATH = "/challenges/programming/challenge.php"
+
+ print method " " PATH " HTTP/1.0" |& FILE
+ print "Host: " HOST "" |& FILE
+
+ return FILE
+}
+
+
+BEGIN {
+ sock = connect("GET")
+ print |& sock
+ close(sock, "to")
+ while (sock |& getline line) {
+ if (match(line, "Set-Cookie:"))
+ cookie = line
+ if (match(line, "span"))
+ text = line
+ }
+ close(sock)
+
+ gsub(" ", " ", text)
+ gsub("<[^>]*>", " ", text)
+ gsub("^ *| *$", "", text)
+ gsub(" +", "+", text)
+ gsub("^[^:]*: *", "", cookie)
+ gsub(" *;.*", "", cookie)
+
+ sock = connect("POST")
+ resp = "answer=" text "&submit=Submit"
+ print "Content-Type: application/x-www-form-urlencoded" |& sock
+ print "Content-Length: " length(resp) |& sock
+ print "Cookie: " cookie |& sock
+ print |& sock
+ print resp |& sock
+ close(sock, "to")
+ while (sock |& getline line)
+ print line
+ close(sock)
+}
--- /dev/null
+#!/bin/bash
+
+sed 's/AUTHOR/Andy Spencer/'
+
+sed 's/AUTHOR/Andy Spencer/g'
+
+sed -f script.sed
--- /dev/null
+#!/bin/bash
+
+sed ':s; s/--$//; T; N; s/\n//; ts' <<-EOF
+ Hello, --
+ world!
+ My name --
+ is --
+ Andy.
+EOF
--- /dev/null
+#!/bin/bash
+
+seq 100 |
+sed '0~15cFizzBuzz
+ 0~05cBuzz
+ 0~03cFizz'
--- /dev/null
+#!/bin/bash
+
+sed -nr '
+ # Buffer input
+ s/^/\n/
+ :s; N; $be; bs; :e
+ s/$/\n/
+ s/ +/ /g
+ s/ *\n/ \n/g
+
+ # Live!
+ :l
+ s/(\n#[^\n]*\n\S+ +[^ 1]+) /\11/g
+ s/(\n\S+ +#[^\n]*\n\S+ +[^ 2]+) /\12/g
+ s/(\n\S+ +\S+ +#[^\n]*\n\S+ +[^ 3]+) /\13/g
+ s/(\n#\S* +[^ 4]+) /\14/g
+ s/(\n\S+ +[^ 5]+) ( +#)/\15\2/g
+ s/(\n\S+ +[^ 6]+) ([^\n]*\n#)/\16\2/g
+ s/(\n\S+ +[^ 7]+) ([^\n]*\n\S+ +#)/\17\2/g
+ s/(\n\S+ +[^ 8]+) ([^\n]*\n\S+ +\S+ +#)/\18\2/g
+ tl
+ s/(\n)([^@\n ])([^@\n ]*)( +)([^\n]+)/\1\5\2@\3\4/g
+ tl
+
+ # Format output
+ s/@//g
+ s/#([0-9]{4,8}) /.\1 /g
+ s/[^0-9]([0-9]{3}) /#\1 /g
+ s/#([0-9]{0,1}) /.\1 /g
+ s/[0-9]/ /g
+
+ # Die!
+ s/ +/ /g;
+ p
+ s/ +/ /g
+ bl
+' <<EOF
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . . . # . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . # . # . . . . . . . . . . . .
+. . . . . . . . . . . . . # # . . . . . . # # . . . . . . . . . . . . # # .
+. . . . . . . . . . . . # . . . # . . . . # # . . . . . . . . . . . . # # .
+. # # . . . . . . . . # . . . . . # . . . # # . . . . . . . . . . . . . . .
+. # # . . . . . . . . # . . . # . # # . . . . # . # . . . . . . . . . . . .
+. . . . . . . . . . . # . . . . . # . . . . . . . # . . . . . . . . . . . .
+. . . . . . . . . . . . # . . . # . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . # # . . . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+EOF
--- /dev/null
+# Clear hold space
+x; s/.*//; x
+
+# Debug input
+s/^/< /
+w /dev/stderr
+s/^< //
+
+# Setup variables:
+s/[$=]/&\\/g
+s/\(:\([^ ]*\) \)\?\(\([^ ]*\) \)\(\([^ ]*\) \)\?\(:\(.*\)\)/AUTH= SERVER= NICK= CHANNEL= CMD=\4 SRC=\2 DST=\6 TO= FROM= MSG=\8/
+s/\(TO=\)\(.*MSG=\([^:,]\+\)[:,]\)/\1\3\2/
+s/\(SRC=\([^!]\+\)!.*\)\(FROM=\)/\1\3\2/
+s/CHANNEL=/&#rhnoise/
+s/NICK=/&rhsed/
+s/SERVER=/&irc.freenode.net/
+s/\(AUTH=\)\(.*TO=rhsed.*FROM=andy753421\)/\1yes\2/
+
+# IRC library commands
+1 { x; s/$/\nUSER andy c $SERVER :$NICK/; x; }
+1 { x; s/$/\nNICK rhsed/; x; }
+/CMD=PING/ { x; s/$/\nPING :$MSG/; x; }
+/CMD=001.*MSG=.*Welcome/ { x; s/$/\nJOIN $CHANNEL/; x; }
+
+# Bot commands
+/MSG=.*\<sed\>/ { x; s/$/\n.say Sed!/; x; }
+/NICK=\([^ ]*\).*MSG=\1:/ { x; s/$/\n.say Hello, $FROM/; x; }
+/MSG=.dup/ { x; s/$/\n.say Dup! $MSG/; x; }
+/MSG=.ping/ { x; s/$/\n.reply Pong!/; x; }
+/AUTH=yes.*MSG=.*die in a fire/Q
+
+# Helper functions
+x
+s/\n.reply /\n.say $FROM: /g
+s/\n.say *\([^\n]*\)/\nPRIVMSG #rhnoise :\1/g
+x
+
+# Replace variables
+G
+:vars
+s/\(.*SERVER=\([^ ]*\).*\n.*\)\$SERVER/\1\2/
+s/\(.*NICK=\([^ ]*\).*\n.*\)\$NICK/\1\2/
+s/\(.*CHANNEL=\([^ ]*\).*\n.*\)\$CHANNEL/\1\2/
+s/\(.*CMD=\([^ ]*\).*\n.*\)\$CMD/\1\2/
+s/\(.*SRC=\([^ ]*\).*\n.*\)\$SRC/\1\2/
+s/\(.*DST=\([^ ]*\).*\n.*\)\$DST/\1\2/
+s/\(.*TO=\([^ ]*\).*\n.*\)\$TO/\1\2/
+s/\(.*FROM=\([^ ]*\).*\n.*\)\$FROM/\1\2/
+s/\(.*MSG=\([^\n]*\)\n.*\)\$MSG/\1\2/
+t vars
+
+## Output
+s/^[^\n]*\n*//
+s/\([$=]\)\\/\1/g
+/./ {
+ w /dev/stdout
+ s/\(^\|\n\)/\1> /g
+ w /dev/stderr
+}
+d
+
+# vim: ft=sed
--- /dev/null
+#!/bin/bash
+
+awk '
+ function hello(name, str) {
+ str = "hello, " name
+ print str
+ }
+ function call(fun, arg) {
+ @fun(arg);
+ }
+ BEGIN {
+ fun = "hello";
+ call(fun, "Andy");
+ }
+'
--- /dev/null
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
--- /dev/null
+#get param
+awk -v "key=$1" '
+ BEGIN {RS=" "; FS="="}
+ $1 ~ key {print $2}
+'
+
+# cut file
+bnd="${CONTENT_TYPE/*boundary\=/}"
+
+awk -v "want=$1" -v "bnd=$bnd" '
+ BEGIN { RS="\r\n" }
+
+ # reset based on boundaries
+ $0 == "--"bnd"" { st=1; next; }
+ $0 == "--"bnd"--" { st=0; next; }
+ $0 == "--"bnd"--\r" { st=0; next; }
+
+ # search for wanted file
+ st == 1 && $0 ~ "^Content-Disposition:.* name=\""want"\"" { st=2; next; }
+ st == 1 && $0 == "" { st=9; next; }
+
+ # wait for newline, then start printing
+ st == 2 && $0 == "" { st=3; next; }
+ st == 3 { print $0 }
+ # head
+' | head -c $((128*1024)) # Limit size to 128K
+
+# List
+awk -v 'rows=4' -v 'cols=60' '
+ FNR==1 { gsub(/.*\//, "", FILENAME);
+ print FILENAME
+ print "-----" }
+ FNR==1,/^$/ { next }
+ /\S/ { i++; printf "%."cols"s\n", $0 }
+ i>=rows { nextfile }
+ ENDFILE { i=0; print "" }
+' $(ls -t db/*)
+
+# Stat
+ls -l --time-style='+%Y %m' db |
+awk -v 'hdr=Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec' '
+ BEGIN { printf "%64s\n", hdr }
+ NR>1 { cnt[$6+0][$7+0]++ }
+ END { for (y in cnt) {
+ printf "%4d", y
+ for (m=1; m<=12; m++)
+ printf "%5s", cnt[y][m]
+ printf "\n" } }'