#!/bin/bash # copyright 2007 Gilbert Ashley # BashTrix tr is an implementation of the 'tr' command # written in pure shell. VERSION=0.2 # show program usage show_usage() { echo echo "Usage: ${0##/*} SET1 SET2 [FILE]..." echo " or: (cat|echo) FILE | ${0##/*} SET1 SET2" echo "Translate or delete characters." echo "Translate, squeeze, and/or delete characters in a line." echo "With no FILE specified, standard input is read." echo " -d delete characters in SET1, do not translate" echo " -s --squeeze-repeats replace characters in SET1" echo " Note: -d and -s cannot be used together." echo " which occur repeatedly with a single character" echo " --help display this help and exit" echo " --version output version information and exit" exit } show_version() { echo ${0##/*}" (BashTrix) $VERSION" echo "Copyright 2007 Gilbert Ashley " echo "This is free software written in pure shell." exit } for WORD in "$@" ; do case $WORD in -d) DELETE_CHARS=1 ; shift ;; -s) SQUEEZE_REPEATS=1 ; shift ;; "-h"|"--help") show_usage ;; "--version") show_version ;; esac done if [[ $DELETE_CHARS ]] && [[ $SQUEEZE_REPEATS ]] ; then show_usage fi if [[ ! $1 ]] ; then show_usage else if [[ $DELETE_CHARS ]] ; then PATTERN_1=$1 PATTERN_2="" shift 1 elif [[ $SQUEEZE_REPEATS ]] ; then PATTERN_1=$1 PATTERN_2=$PATTERN_1 shift 1 else PATTERN_1=$1 PATTERN_2=$2 shift 2 fi fi # echo $PATTERN_1:$SIZEOF_PATTERN_1 $PATTERN_2:$SIZEOF_PATTERN_2 if [[ $# -gt 0 ]] ; then while [[ $# -gt 0 ]] ; do FILE_NAME="$1" if [ ! -r "$1" ] ; then echo "Cannot find file $1" 1>&2 exit 1 else FILE_LINE_COUNT=0 LINE= IFS= while read LINE ; do # add the curent line to the line counter (( FILE_LINE_COUNT++ )) OUTPUT_STRING= STRING=$LINE while [[ "$STRING" != "" ]] ; do CHUNK_CONTENTS=$(echo ${STRING:0:1}) #NEXT_CHUNK_CONTENTS=$(echo ${STRING:$OFFSET:$OFFSET}) #echo $SIZEOF_STRING:$OFFSET $CHUNK_CONTENTS $NEXT_CHUNK_CONTENTS #exit if [[ ${CHUNK_CONTENTS} = $PATTERN_1 ]] ; then if [[ $DELETE_CHARS ]] ; then OUTPUT_STRING=$OUTPUT_STRING STRING=${STRING:1} elif [[ $SQUEEZE_REPEATS ]] ; then NEXT_CHUNK_CONTENTS=$(echo ${STRING:1:1}) if [[ $NEXT_CHUNK_CONTENTS = $PATTERN_1 ]] ; then # add the PATTERN to OUTPUT OUTPUT_STRING=$OUTPUT_STRING$PATTERN_1 # increment by two OFFSETS to remove repeating PATTERN STRING=${STRING:2} else OUTPUT_STRING=$OUTPUT_STRING$PATTERN_1 STRING=${STRING:1} fi else OUTPUT_STRING=$OUTPUT_STRING$PATTERN_2 STRING=${STRING:1} fi #echo $OUTPUT_STRING $STRING #exit else OUTPUT_STRING=$OUTPUT_STRING$CHUNK_CONTENTS STRING=${STRING:1} #echo $OUTPUT_STRING $STRING #exit fi #break #echo $OUTPUT_STRING $STRING #exit done #shift echo $OUTPUT_STRING done <"$1" fi # go to next FILE in $@ shift done else # piped input is presumed to be separated into lines already FILE_NAME="STDIN" # output the requested lines in the file FILE_LINE_COUNT=0 LINE= IFS= while read LINE ; do # add the curent line to the line counter (( FILE_LINE_COUNT++ )) OUTPUT_STRING= STRING=$LINE while [[ "$STRING" != "" ]] ; do SIZEOF_STRING=${#STRING} OFFSET=${SIZEOF_PATTERN_1} CHUNK_CONTENTS=$(echo ${STRING:0:$OFFSET}) #echo $SIZEOF_STRING:$OFFSET $CHUNK_CONTENTS #exit if [[ ${CHUNK_CONTENTS} = $PATTERN_1 ]] ; then if [[ $DELETE_CHARS ]] ; then OUTPUT_STRING=$OUTPUT_STRING STRING=${STRING:$OFFSET} else OUTPUT_STRING=$OUTPUT_STRING$PATTERN_2 STRING=${STRING:$OFFSET} fi #echo $OUTPUT_STRING $STRING #exit else OUTPUT_STRING=$OUTPUT_STRING$CHUNK_CONTENTS STRING=${STRING:$OFFSET} #echo $OUTPUT_STRING $STRING #exit fi #echo $OUTPUT_STRING $STRING #exit done echo $OUTPUT_STRING # go to next line in stdin shift done fi