Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/sh
- # readvars [-d] [-f filter] [-F field:filter] [-L limit] [-n "var ..."] \
- # [-s sep [-c]] [-t var] [--] cmd ...
- #
- # For each line of output generated by ``cmd ...'', set a series of numbered
- # variables (default "line1", "line2", etc.). Also sets a variable containing
- # the number of lines processed (default "lines"). If ``cmd ...'' is "-", NULL,
- # or missing, lines are read instead from stdin.
- #
- # If `-d' is given, debugging information is provided on stderr.
- #
- # If ``-f filter'' is given, only lines matching filter regular expression are
- # processed.
- #
- # If ``-F field:filter'' is given, only lines where numbered field matches the
- # filter regular expression are processed. If field is zero, acts the same as
- # ``-f filter''.
- #
- # If ``-L limit'' is given, process at-most limit number of lines. When
- # combined with ``-f filter'', process at-most limit number of lines matching
- # filter regular expression. Default value is `0' and to process all lines.
- #
- # If ``-n "foo bar baz rest"'' is given, the first word on the first line is
- # assigned to variable "foo1", 2nd-word 1st-line to "bar1", 3rd-word 1st-line
- # to "baz1", and any words remaining on line-1 are assigned to "rest1". The
- # last variable name always contains the remainder of the line. Default value
- # if not present is simply "line".
- #
- # If ``-s sep'' is given, use sep as the separator between fields. If `-c' is
- # given, the space between sequential separators are counted as empty words.
- #
- # If ``-t variable'' is given, the total number of lines processed is assigned
- # to "variable" (default value is "lines")..
- #
- # If `--' is given, any further potential option flags are taken as part of
- # command to execute.
- #
- #
- # The return status is that of ``cmd [args ...]''.
- #
- readvars()
- {
- local OPTIND=1 OPTFLAG __readvars_flag
- local __readvars_count_nulls=
- local __readvars_debug=
- local __readvars_filter=
- local __readvars_Ffilter=
- local __readvars_Ffilter_field=
- local __readvars_limit=0
- local __readvars_sep=
- local __readvars_total=
- local __readvars_vars=
- while getopts cdf:F:L:n:s:t: __readvars_flag; do
- case "$__readvars_flag" in
- c) __readvars_count_nulls=1 ;;
- d) __readvars_debug=1 ;;
- f) __readvars_filter="$OPTARG" ;;
- F) __readvars_Ffilter="${OPTARG#*:}"
- __readvars_Ffilter_field="${OPTARG%%:*}" ;;
- L) __readvars_limit="$OPTARG" ;;
- n) __readvars_vars="$OPTARG" ;;
- s) __readvars_sep="$OPTARG" ;;
- t) __readvars_total="$OPTARG" ;;
- esac
- done
- shift $(( $OPTIND - 1 ))
- eval "$( awk \
- -F "${__readvars_sep:-$IFS}" \
- -v IFS="$IFS" \
- -v count_nulls="${__readvars_count_nulls:-0}" \
- -v debug="${__readvars_debug:-0}" \
- -v filter="$__readvars_filter" \
- -v Ffilter="$__readvars_Ffilter" \
- -v Ffilter_field="${__readvars_Ffilter_field:-0}" \
- -v sep="${__readvars_sep:-$IFS}" \
- -v total="${__readvars_total:-lines}" \
- -v vars="${__readvars_vars:-line}" \
- -- '
- ############################################ FUNCTIONS
- function esc(str) { gsub(/'\''/, "&\\\\&&", str); return str }
- function set(k, v)
- {
- parent_eval = sprintf("%s='\''%s'\''", k, esc(v))
- if (debug) print "DEBUG:", parent_eval > "/dev/stderr"
- print parent_eval
- }
- function seti(key, val) { set(key i, val) }
- function extract_value(line, varnum)
- {
- match(line, sprintf(count_nulls ? "^[^%s]*[%s]?" : \
- "^[%s]*[^%s]+", sep, sep))
- if (varnum == nvars) {
- value = substr(line, RSTART)
- sub(sprintf("[%s]*$", sep), "", value)
- } else
- value = substr(line, RSTART, RLENGTH)
- sub(sprintf(count_nulls ? \
- "[%s]?$" : "^[%s]*", sep), "", value)
- seti(varlist[varnum], value)
- return substr(line, RSTART + RLENGTH)
- }
- function setivars(vars, line)
- {
- for (v = 1; v <= nvars; v++)
- line = extract_value(line, v)
- }
- function match_filters(line)
- {
- return (line ~ filter && $Ffilter_field ~ Ffilter)
- }
- ############################################ MAIN
- BEGIN {
- nvars = split(vars, varlist, "[" IFS "]+")
- cmd = "eval"
- if (ARGC <= 1 || (ARGC == 2 && ARGV[1] == "-")) {
- ARGC = 2
- ARGV[1] = "cat"
- }
- for (a = 1; a < ARGC; a++)
- cmd = cmd " '\''" esc(ARGV[a]) "'\''"
- retval = 0
- while (cmd | getline)
- {
- if (match_filters($0)) {
- if (++i > (limit > 0 ? limit : i)) {
- retval = close(cmd)
- exit
- }
- setivars(varlist, $0)
- }
- }
- retval = close(cmd)
- exit
- }
- END {
- set(total, i == "" ? 0 : i)
- printf "( exit %u )", int(retval / 256)
- }
- ' "$@" )"
- }
- ### BEGIN UNIT-TEST CODE
- #
- #readvars "$@"
- #echo "?=[$?]"
- #
- #args=line total=lines
- #while getopts cdf:L:n:s:t: flag; do
- # case "$flag" in
- # n) args="$OPTARG" ;;
- # t) total="$OPTARG" ;;
- # esac
- #done
- #shift $(( $OPTIND - 1 ))
- #
- #eval count=\"\$$total\"
- #echo "$total=[$count]"
- #n=1
- #while [ $n -le $count ]; do
- # for arg in $args; do
- # eval value=\"\$$arg$n\"
- # echo "$arg$n=[$value]"
- # done
- # n=$(( $n + 1 ))
- #done
- #
- ### END UNIT-TEST CODE
- #
- # Examples:
- #
- echo ">>> Example 1. List of users in passwd(5)"
- readvars -cs: -n"user rest" < /etc/passwd
- echo "?=[$?]"
- n=1
- while [ $n -le ${lines:-0} ]; do
- eval user=\"\$user$n\"
- echo "$user"
- n=$(( $n + 1 ))
- done
- echo
- echo ">>> Example 2. Get homedir of a specific user in passwd(5)"
- PASSWD_FIELDS="user hash uid gid gecos home shell"
- unset home1
- readvars -cs: -n"$PASSWD_FIELDS" -F1:'^root$' -L1 < /etc/passwd
- echo "?=[$?]"
- echo "root's home directory is: ${home1:-**UNKNOWN**}"
- echo
- echo ">>> Example 3. List primary group membership names for each user"
- PASSWD_FIELDS="user hash uid gid gecos home shell"
- GROUP_FIELDS="group chkgrp_hash group_gid members"
- readvars -t nusers -cs: -n"$PASSWD_FIELDS" < /etc/passwd
- echo "?=[$?]"
- readvars -t ngroups -cs: -n"$GROUP_FIELDS" < /etc/group
- echo "?=[$?]"
- g=1
- while [ $g -le ${ngroups:-0} ]; do
- eval group=\"\$group$g\" group_gid=\"\$group_gid$g\"
- eval group_name_$group_gid=\"\$group$g\"
- g=$(( $g + 1 ))
- done
- u=1
- while [ $u -le ${nusers:-0} ]; do
- eval user=\"\$user$u\" user_gid=\"\$user_gid$u\"
- eval user_group=\"\$group_name_$user_gid\"
- echo "user=[$user] user_group=[$user_group]"
- u=$(( $u + 1 ))
- done
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement