/one-liner

one-liner

Primary LanguageShell

What ?

Some one-liner or minimalist bash, jq and awkstuff

Project selected vars and func as bash workspace

Workspace

  • We want to count the number of syslog lines by hour for all syslog files on any remote node (using ssh localhost to demo)
: name=syslog-by-hours

declare -A jq=()
# Get epochs from syslog lines
jq[epochs]='./"." | first | strptime("%Y-%m-%dT%H:%M:%S") | mktime'
# Count syslog lines by hours
jq[by-hours]='map(gmtime) | group_by(.[3]) | map(length)[]'

# Use jq code associated with a func
jqf () { jq -M "${jq[${FUNCNAME[1]}]}" "$@"; }

# All compressed and uncompressed syslog files concatenated
syslogs () { zgrep . /var/log/syslog* | cut -d: -f2-; }

# Use our jq code
epochs () { syslogs | jqf -R | sort -n; }
by-hours () { epochs | jqf -s; }

Play it on remote node

  • use with
: name=syslog-by-hours

source with.sh
lib=(jq jqf syslogs epochs by-hours)
  • Call a specific func (e.g. for testing)
with ${lib[@]} -- syslogs | ssh localhost -l root bash | head
  • Default to call the last arg of with
$ with ${lib[@]} | ssh localhost -l root bash | fmt
1463 689 415 421 420 681 494 770 1267 7902 1920 849 2064 2091 5199 1401
758 1282 4990 4468 1692 1037 1013 1093

Add a local minimal plot

with ${lib[@]} | ssh localhost -l root bash | jq -sr 'include "zoom"; plot(sqrt; 80; 20)'

░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░███░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░███░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░███░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░███░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░███░░░░░░░░░░░░░░███░░░░░░░░░░███░░░░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░███░░░░░░░░░░░░░░███░░░░░░░░░░██████░░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░████░░░░░░░░░░░░░███░░░░░░░░░░███████░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░████░░░░░░░░░░░░████░░░░░░░░░░███████░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░████░░░░░░░░░░░░████░░░░░░░░░░███████░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░████░░░░░░░░░███████░░░░░░░░░░███████░░░░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██████░░░░██████████░░░░░░░░░░██████████░░░░░░░░░░
███░░░░░░░░░░░░░░░░░░░░░░░░░░░███████░░░█████████████░░░░░░░██████████░░░░░░░░░░
████░░░░░░░░░░░░░░░░░░░░░░░██████████░░░█████████████░░░░█████████████████░░░███
██████░░░░░░░░░░░░░░░░░░░░████████████████████████████░░████████████████████████
███████░░░░░░░░░░███░░░█████████████████████████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████

Output func on one line

  • See func-on-one-line.sh
  • Aliased as func
  • Argument of alias is expanded (so that func func is exanped as func-on-one-line func-on-one-line)
$ source func-on-one-line.sh
$ func func
func-on-one-line () { local -n a=MAPFILE; mapfile -t < <(declare -f ${1:?}); ((${#a[*]})) || return 1; local i t; for ((i = 2; i < $((${#a[*]} - 1)); ++i)) do t=${a[(($i + 1))]}; printf -v n -- ${t/\%/%%}; [[ ${#n} == 1 && ${n:(-1)} == "}" ]] || [[ ${#n} == 2 && ${n:(-2)} == "};" ]] && a[$i]+=";"; done; a[-1]+=';'; echo ${a[@]}; };

Allow easy copy-paste and on the fly edition

source <(func func | sed s/^func-on-one-line/fool/)

Misc funcs

files=(with func-on-one-line misc bash-from-md short)
sources () { for file in ${files[@]}; do source $file.sh; done; }
items () { for file in ${files[@]}; do $file.list; done; }
$ sources; items | loop args | sort -u | loop item
args () { for arg in "$@"; do echo $arg; done; };
declare -A awk=([bash-from-md]="/^\`\`\`bash/ { ++b; next } b && /^: name=/ { FS = \"=\"; \$0 = \$0; s = \$2 } /^\`\`\`\$/ { --b; s = \"\" } b && s { t[s] = t[s] \$0 RS } END { print t[n] }" )
awkf () { awk "$@" "${awk[${FUNCNAME[1]}]}"; };
bash-from-md () { awkf -v n=${1:?}; };
func-on-one-line () { local -n a=MAPFILE; mapfile -t < <(declare -f ${1:?}); ((${#a[*]})) || return 1; local i t; for ((i = 2; i < $((${#a[*]} - 1)); ++i)) do t=${a[(($i + 1))]}; printf -v n -- ${t/\%/%%}; [[ ${#n} == 1 && ${n:(-1)} == "}" ]] || [[ ${#n} == 2 && ${n:(-2)} == "};" ]] && a[$i]+=";"; done; a[-1]+=';'; a=("${a[@]% }"); echo "${a[@]##*( )}"; };
item () { declare -p $1 &> /dev/null && declare -p $1; func-on-one-line $1; };
loop () { while read; do eval "$@" $REPLY; done; };
short () { : ${1:?}; until [[ $# == 1 || $1 == -- ]]; do item $1; shift; done; if [[ $1 == -- ]]; then shift; fi; item $1; echo $@; };
with () { : ${1:?}; until [[ $# == 1 || $1 == -- ]]; do with.decl $1; shift; done; if [[ $1 == -- ]]; then shift; fi; with.decl $1; echo $@; };
with.decl () { declare -p $1 &> /dev/null && declare -p $1; declare -f $1; };

Extract bash stanzas from mardown files

Clean current workspace

exec bash

Source the tool

source bash-from-md.sh

Use it to source stanza syslog-by-hours from with.md

source <(< with.md bash-from-md syslog-by-hours)

Use the sourced stanza

$ with ${lib[@]} | ssh localhost -l root bash | fmt
1463 689 415 421 420 681 494 770 1267 7902 1920 849 2174 2189 5233 1428
813 1321 5039 4499 1810 1037 1013 1093

Concise version of with

  • See short.sh
  • Concise by output not by src
  • Use func-on-one-line instead of declare -f in a modified with
  • Show a workspace as a sequence of item (var or func) each on a line

Show expasion of short

$ source short.sh; source misc.sh
$ short.list | loop args | loop item
func-on-one-line () { local -n a=MAPFILE; mapfile -t < <(declare -f ${1:?}); ((${#a[*]})) || return 1; local i t; for ((i = 2; i < $((${#a[*]} - 1)); ++i)) do t=${a[(($i + 1))]}; printf -v n -- ${t/\%/%%}; [[ ${#n} == 1 && ${n:(-1)} == "}" ]] || [[ ${#n} == 2 && ${n:(-2)} == "};" ]] && a[$i]+=";"; done; a[-1]+=';'; a=("${a[@]% }"); echo "${a[@]##*( )}"; };
item () { declare -p $1 &> /dev/null && declare -p $1; func-on-one-line $1; };
short () { : ${1:?}; until [[ $# == 1 || $1 == -- ]]; do item $1; shift; done; if [[ $1 == -- ]]; then shift; fi; item $1; echo $@; };

Get a workspace

exec bash
source bash-from-md.sh
source <(< with.md bash-from-md syslog-by-hours)
source short.sh

Show concise version of workspace

$ short ${lib[@]}
declare -A jq=([epochs]="./\".\" | first | strptime(\"%Y-%m-%dT%H:%M:%S\") | mktime" [by-hours]="map(gmtime) | group_by(.[3]) | map(length)[]" )
jqf () { jq -M "${jq[${FUNCNAME[1]}]}" "$@"; };
syslogs () { zgrep . /var/log/syslog* | cut -d: -f2-; };
epochs () { syslogs | jqf -R | sort -n; };
by-hours () { epochs | jqf -s; };
by-hours