#!/bin/bash show_usage() { echo echo ${0##/*}" Usage:" echo " Cut FIELDS from STRING using separator SEP" echo "${0##/} -fFIELDS -dSEP STRING" echo exit } case $1 in ""|"-h"|"--help") show_usage ;; esac # Minimum number of arguments needed by this program MINARGS=3 # count the number of arguments given COUNT=0 for ARGV in "$@" ; do (( COUNT++ )) ; done ARGC=$COUNT [[ $DEBUG ]] && echo "ARGC=$COUNT" ##debug # check to make sure enough arguments were given if [[ $ARGC -lt $MINARGS ]] ; then [[ $DEBUG ]] && echo "Too few arguments given (Minimum:$MINARGS)" show_usage fi # Assign the variables to ARGV[?] COUNT=0 for ARGV in "$@" ; do (( COUNT++ )) ; declare ARG_${COUNT}="$ARGV" [[ $DEBUG ]] && echo $ARG_$COUNT done [[ $DEBUG ]] && echo "$ARG_1 $ARG_2 $ARG_3" ##debug # process_arguments # could use for ARGV_? in ARGC for WORD in "$@" ; do case $WORD in --) echo "End of arguments" ; shift ;; # --*) echo "Long option" ; shift ;; -*) true ; case $WORD in # -f=?) [[ $DEBUG ]] && echo "Short single FIELD Option using '='" # FIELDS=${WORD:3:1} FIELDS=${WORD##*=} [[ $DEBUG ]] && echo FIELDS=$FIELDS shift ;; -f=*|--fields=*) [[ $DEBUG ]] && echo "Short range FIELD Option using '='" # FIELDS=${WORD:3} FIELDS=${WORD##*=} [[ $DEBUG ]] && echo FIELDS=$FIELDS shift ;; -f?) [[ $DEBUG ]] && echo "Short single FIELD Option" #FIELDS=${WORD:2:1} FIELDS=${WORD##*f} [[ $DEBUG ]] && echo FIELDS=$FIELDS shift ;; -f) [[ $DEBUG ]] && echo "Short split FIELD Option" # if the next argument begins with a dash if [[ ${2:0:1} != "-" ]] ; then FIELDS=$2 [[ $DEBUG ]] && echo FIELDS=$FIELDS shift 2 else echo "Missing argument" exit fi ;; -f*) [[ $DEBUG ]] && echo "Short FIELD Option range" #FIELDS=${WORD:2} FIELDS=${WORD##*f} [[ $DEBUG ]] && echo FIELDS=$FIELDS shift ;; -d*) [[ $DEBUG ]] && echo "Short-short DEL Option" SEP=${WORD##*d} [[ $DEBUG ]] && echo SEP=$SEP shift ;; esac ;; esac done STRING="$@" [[ $DEBUG ]] && echo STRING="$@" ######### ignore() { if [[ $3 ]] ; then FIELDS=${1:2:1} SEP=${2:2:1} STRING=${3} else show_usage fi } FIELD=$FIELDS DEL=$SEP STRING=$STRING [[ $DEBUG ]] && echo FIELD=$FIELDS DEL=$SEP STRING=$STRING ################## # function _length counts the characters in a string and # echo the result. Requires PARSESTRING function _length() { COUNT=0 while [[ $PARSESTRING != "" ]] ; do # get the first remaining character FC=${PARSESTRING:0:1} # cut the first character PARSESTRING="${PARSESTRING#${FC}*}" (( COUNT++ )) done echo $COUNT } # example usage PARSESTRING=$STRING [[ $DEBUG ]] && echo STRINGLEN=$(_length $PARSESTRING) # function _freq counts the number of matches # of PATTERN in PARSESTRING and returns FREQ function _freq() { FREQ=0 ! [[ $PATTERN ]] && PATTERN=$1 ! [[ $PARSESTRING ]] && PARSESTRING=$2 while [[ $PARSESTRING != "" ]] ; do case $PARSESTRING in *$PATTERN*) FREQ=$(( FREQ + 1 )) ; PARSESTRING=${PARSESTRING#*${PATTERN}} ;; *) PARSESTRING="" ;; esac done echo $FREQ } # example usage #PARSESTRING=$STRING #PATTERN=$SEP #[[ $DEBUG ]] && echo "Found $(_freq) matches." # _freq $SEP $STRING # _print_field # print the contents of a single FIELD before the SEP in PARSESTRING # Requires/defaults: FIELD=$1 PATTERN=$2 PARSESTRING=$3 function _print_field() { FREQ=0 ! [[ $FIELD ]] && FIELD=$1 ! [[ $PATTERN ]] && PATTERN=$2 ! [[ $PARSESTRING ]] && PARSESTRING=$3 while [[ $PARSESTRING != "" ]] ; do case $PARSESTRING in *$PATTERN*) FREQ=$(( FREQ + 1 )) ; # echo FIELD_${FREQ}=${PARSESTRING%%${PATTERN}*} # declare FIELD_${FREQ}=${PARSESTRING%%${PATTERN}*} # [[ $DEBUG ]] && echo "FIELD_$FREQ=$FIELD_FREQ" if [[ $FIELD = $FIELD_$FREQ ]] ; then # echo FIELD_${FREQ}=${PARSESTRING%%${PATTERN}*} echo ${PARSESTRING%%${PATTERN}*} fi PARSESTRING=${PARSESTRING#*${PATTERN}} ;; *) PARSESTRING="" ;; esac done } # example # _print_field $FIELD $SEP $STRING case $FIELDS in 2) [[ $DEBUG ]] && echo "single second FIELD is a special case" # if FIELD 2 is specified alone it means the contents after the first SEP # split off what's to the right of the first SEP STUB=${PARSESTRING#*$SEP} #echo $STUB # keep only whats before the next SEP (if any) # ./cut -f2 -d- -hello.world.to.you -returns: #hello.world.to.you # ./cut -f2 -d- -hello-world.to.you -returns: #hello # ./cut -f1-2 -d- -hello-world.to.you -returns: #-hello OUTPUT=${STUB%$SEP*} echo $OUTPUT ;; ?-?) [[ $DEBUG ]] && echo "FIELDS is a closed (between) range" START=${FIELDS:0:1} FINISH=${FIELDS:2:1} # echo $START $FINISH COUNT=0 OUTPUT="" STUB="" while [[ $COUNT -lt $START ]] ; do true (( COUNT++ )) done while [[ $COUNT -le $FINISH ]] ; do FIELD=$COUNT [[ $DEBUG ]] && echo FIELD=$COUNT # insert code here to cut each field? sort of if [[ $FIELD = 2 ]] ; then OUTPUT=${STRING%$SEP*} else STUB=$(_print_field $FIELD $SEP $STRING) OUTPUT=$OUTPUT$SEP$STUB fi (( COUNT++ )) done # strip off the extra SEP at the beginning OUTPUT=${OUTPUT#*$SEP} echo $OUTPUT ;; ?-) echo "FIELDS is an open range" ;; ?) [[ $DEBUG ]] && echo "FIELDS is a single value" OUTPUT=$(_print_field $FIELD $SEP $STRING) echo $OUTPUT ;; esac