From: Andy Spencer Date: Sat, 16 Mar 2013 23:55:30 +0000 (+0000) Subject: Add sed and awk presentation X-Git-Url: http://pileus.org/git/?p=~andy%2Fsfvlug;a=commitdiff_plain;h=4c73130695082dc72758db49824005e6bca43872 Add sed and awk presentation --- 4c73130695082dc72758db49824005e6bca43872 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0c0b127 --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +# Misc +*~ +*.swp + +# C output +*.o +*.a + +# Latex output +*.aux +*.log +*.nav +*.out +*.snm +*.toc +*.vrb diff --git a/awk/ext/mkfile b/awk/ext/mkfile new file mode 100644 index 0000000..1171fc6 --- /dev/null +++ b/awk/ext/mkfile @@ -0,0 +1,14 @@ +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 diff --git a/awk/ext/select.awk b/awk/ext/select.awk new file mode 100644 index 0000000..5b45a7a --- /dev/null +++ b/awk/ext/select.awk @@ -0,0 +1,33 @@ +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 "]" + } +} diff --git a/awk/ext/select.c b/awk/ext/select.c new file mode 100644 index 0000000..d379167 --- /dev/null +++ b/awk/ext/select.c @@ -0,0 +1,149 @@ +/* + * 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); +} diff --git a/awk/sedawk.pdf b/awk/sedawk.pdf new file mode 100644 index 0000000..35a44bb Binary files /dev/null and b/awk/sedawk.pdf differ diff --git a/awk/sedawk.tex b/awk/sedawk.tex new file mode 100644 index 0000000..1a10104 --- /dev/null +++ b/awk/sedawk.tex @@ -0,0 +1,404 @@ +\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 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} diff --git a/awk/src/awk-0-simpleawk.sh b/awk/src/awk-0-simpleawk.sh new file mode 100755 index 0000000..f7609c9 --- /dev/null +++ b/awk/src/awk-0-simpleawk.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +awk 'BEGIN { print "Hello, world" }' diff --git a/awk/src/awk-1-sum b/awk/src/awk-1-sum new file mode 100755 index 0000000..981faad --- /dev/null +++ b/awk/src/awk-1-sum @@ -0,0 +1,4 @@ +#!/bin/awk -f +BEGIN { RS="[^0-9eE.+-]" } +// { sum += $0 } +END { print sum } diff --git a/awk/src/awk-2-avg b/awk/src/awk-2-avg new file mode 100755 index 0000000..342a65e --- /dev/null +++ b/awk/src/awk-2-avg @@ -0,0 +1,4 @@ +#!/bin/awk -f +BEGIN { RS="[^0-9eE.+-]+" } +/[0-9]/ { sum += $0; cnt++ } +END { print sum / cnt } diff --git a/awk/src/awk-3-awklife.sh b/awk/src/awk-3-awklife.sh new file mode 100755 index 0000000..2bc4cf1 --- /dev/null +++ b/awk/src/awk-3-awklife.sh @@ -0,0 +1,74 @@ +#!/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 diff --git a/awk/src/awk-4-vcutfile.sh b/awk/src/awk-4-vcutfile.sh new file mode 100755 index 0000000..3ca4a72 --- /dev/null +++ b/awk/src/awk-4-vcutfile.sh @@ -0,0 +1,22 @@ +#!/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 diff --git a/awk/src/awk-5-vgetparam.sh b/awk/src/awk-5-vgetparam.sh new file mode 100755 index 0000000..0798e2e --- /dev/null +++ b/awk/src/awk-5-vgetparam.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# get param +awk -v "key=member" ' + BEGIN {RS=" "; FS="="} + $1 ~ key {print $2} +' <<-EOF + name=andy member=sfvlug +EOF diff --git a/awk/src/awk-6-vlist.sh b/awk/src/awk-6-vlist.sh new file mode 100755 index 0000000..a055424 --- /dev/null +++ b/awk/src/awk-6-vlist.sh @@ -0,0 +1,12 @@ +#!/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/*) diff --git a/awk/src/awk-7-vstat.sh b/awk/src/awk-7-vstat.sh new file mode 100755 index 0000000..886152b --- /dev/null +++ b/awk/src/awk-7-vstat.sh @@ -0,0 +1,12 @@ +#!/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" } }' diff --git a/awk/src/challenge.awk b/awk/src/challenge.awk new file mode 100755 index 0000000..b613750 --- /dev/null +++ b/awk/src/challenge.awk @@ -0,0 +1,46 @@ +#!/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) +} diff --git a/awk/src/sed-0-simplesed.sh b/awk/src/sed-0-simplesed.sh new file mode 100755 index 0000000..eac4879 --- /dev/null +++ b/awk/src/sed-0-simplesed.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +sed 's/AUTHOR/Andy Spencer/' + +sed 's/AUTHOR/Andy Spencer/g' + +sed -f script.sed diff --git a/awk/src/sed-1-branching.sh b/awk/src/sed-1-branching.sh new file mode 100755 index 0000000..93dce4a --- /dev/null +++ b/awk/src/sed-1-branching.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +sed ':s; s/--$//; T; N; s/\n//; ts' <<-EOF + Hello, -- + world! + My name -- + is -- + Andy. +EOF diff --git a/awk/src/sed-2-fizzbuzz.sh b/awk/src/sed-2-fizzbuzz.sh new file mode 100755 index 0000000..b3d88f4 --- /dev/null +++ b/awk/src/sed-2-fizzbuzz.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +seq 100 | +sed '0~15cFizzBuzz + 0~05cBuzz + 0~03cFizz' diff --git a/awk/src/sed-3-sedlife.sh b/awk/src/sed-3-sedlife.sh new file mode 100755 index 0000000..b4f1407 --- /dev/null +++ b/awk/src/sed-3-sedlife.sh @@ -0,0 +1,62 @@ +#!/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 +' </ { 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 diff --git a/awk/src/test.sh b/awk/src/test.sh new file mode 100644 index 0000000..849a391 --- /dev/null +++ b/awk/src/test.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +awk ' + function hello(name, str) { + str = "hello, " name + print str + } + function call(fun, arg) { + @fun(arg); + } + BEGIN { + fun = "hello"; + call(fun, "Andy"); + } +' diff --git a/awk/src/test.txt b/awk/src/test.txt new file mode 100644 index 0000000..f00c965 --- /dev/null +++ b/awk/src/test.txt @@ -0,0 +1,10 @@ +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 diff --git a/awk/src/vpaste.sh b/awk/src/vpaste.sh new file mode 100755 index 0000000..c7b4aca --- /dev/null +++ b/awk/src/vpaste.sh @@ -0,0 +1,48 @@ +#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" } }' diff --git a/awk/xkcd.png b/awk/xkcd.png new file mode 100644 index 0000000..acbc243 Binary files /dev/null and b/awk/xkcd.png differ