3
\$\begingroup\$

This is a simple Bash script to provide menu driven manuals and standard operating procedures.

Sops and mans with the extension .sopman.txt will be loaded.

The file motd is required, it is intended to prompt the user with a banner containing useful and or up to date information.

Use the markup +color+ to colorize a line, see colors.sopman.txt for complete list of supported colors.

Github Project

See Find and Replace Question

Powershell Version Code Review

#!/usr/bin/env bash
#.-----.-----.-----.--------.---.-.-----.
#|__ --| _ | _ | | _ | |
#|_____|_____| __|__|__|__|___._|__|__|
# |__| Matthew A. Brassey
version=1.0.0
license="
sopman v${version}
Copyright (C) 2017 Matthew A. Brassey
 This program 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.
 This program 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, see <http://www.gnu.org/licenses/>.
"
help="
Usage: ./sopman.sh [--help|--version]
[options]
 --search Search sopman archive for a string. '--search <search string>'
 --motd Display message of the day.
 --license Show lisense information.
"
#Variables
args=("$@")
sops=(sops/*.sopman.txt)
stoploop="false"
endscript="false"
length="${#sops[@]}"
#Colors
lineColor='\e[0m'
reset="\e[0m";
black="\e[1;30m";
blue="\e[1;34m";
cyan="\e[1;36m";
green="\e[1;32m";
purple="\e[1;35m";
red="\e[1;31m";
white="\e[1;37m";
yellow="\e[1;33m";
header="$(echo -e "${cyan}================================================================[sopman]====${reset}")"
footer="$(echo -e "${cyan}============================================================================${reset}")"
#Functions
function search() {
 echo -e "${green}Search results for \"$searchString\":${reset}\n"
 grep -rnw sops/ -e "$searchString" --include "*.sopman.txt"
}
function motd() {
 clear
 echo "$header"
 while read -r line; do
 GETCOLOR "$line"
 newLine=$(echo "$line" | sed "s/+[a-Z]\++//g")
# shopt -s extglob
# new_line=${line//(\+)}
 echo -e "${lineColor}${newLine}${reset}"
 done <"motd"
 echo "$footer"
}
function menu0 {
 fcount="0"
 clear
 echo "$header"
 motd
 echo -e "${green}0] Search ${reset}"
 for sop in "${sops[@]}"
 do
 let fcount=fcount+1
 echo -e "${green}$fcount) ${sop:5:-11} ${reset}"
 done
 echo "$footer"
}
function GETCOLOR() {
 if [[ 1ドル =~ \+[a-Z]+\+? ]]; then
 local match=${BASH_REMATCH[0]};
 case $match in
 "+black+") lineColor=$black;;
 "+red+") lineColor=$red;;
 "+green+") lineColor=$green;;
 "+blue+") lineColor=$blue;;
 "+purple+") lineColor=$purple;;
 "+cyan+") lineColor=$cyan;;
 "+yellow+") lineColor=$yellow;;
 "+white+") lineColor=$white;;
 *) lineColor=$reset;;
 esac
 fi
}
for ((arg=0;arg<"${#args[@]}";arg++)); do
 [ "${args[$arg]}" == "--version" ] && echo "${version}" && exit
 [ "${args[$arg]}" == "--help" ] && echo "${help}" && exit
 [ "${args[$arg]}" == "--license" ] && echo "${license}" && exit
 [ "${args[$arg]}" == "--search" ] && searchString=${args[$arg+1]} && clear && echo "$header" && search && echo "$footer" && exit
 [ "${args[$arg]}" == "--motd" ] && clear && echo "$header" && motd && exit
 #[ "${args[$arg]}" == "--" ] && echo ${args[$arg]}
done
while [ $endscript = "false" ]
do
 menu0 
 while [ $stoploop = "false" ]
 do
 printf "Enter your selection (q to quit) : "
 read -r input1
 if [ "$input1" = "q" ]; then
 echo -e "${cyan}Bye-Bye${reset}"
 exit
 fi
 if [ "$input1" -eq "0" ]; then
 printf "Search for: "
 read -r searchString
 clear
 echo "$header"
 search
 echo "$footer"
 printf "[ 'm' to return to menu, anything else to quit ] : "
 read -r input3
 if [ "$input3" = "m" ]; then
 break
 else 
 echo -e "${cyan}Bye-Bye${reset}"
 exit
 fi
 fi
 if [ "$input1" -ge "1" ] && [ "$input1" -le "$length" ]; then
 clear
 echo "$header"
 while read -r line; do
 GETCOLOR "$line"
 newLine=$(echo "$line" | sed "s/+[a-Z]\++//g")
 echo -e "${lineColor}${newLine}${reset}"
 done <"${sops[$input1-1]}"
 echo "$footer"
 printf "[ 'm' to return to menu, anything else to quit ] : "
 read -r input2
 if [ "$input2" = "m" ]; then
 break
 else
 echo -e "${cyan}Bye-Bye${reset}"
 exit
 fi
 else
 echo -e "${red}ERROR! Please select an option : ${reset}"
 retryCount=$((retryCount+1))
 if [ "$retryCount" -ge "3" ]; then
 echo -e "${red}EXIT!${reset}"
 exit
 fi
 fi
 done
done
asked Mar 18, 2017 at 19:02
\$\endgroup\$
2
  • \$\begingroup\$ What are you looking for from the code review? \$\endgroup\$ Commented Mar 18, 2017 at 22:32
  • \$\begingroup\$ It would be great to have an answer to the Find and Replace Question . Also looking for corrections, optimizations & general improvements or suggestions. \$\endgroup\$ Commented Mar 19, 2017 at 0:09

1 Answer 1

2
\$\begingroup\$

I don't have time for a full review, but I'll just mention that you seem to have terminal-specific escapes here:

lineColor='\e[0m'
reset="\e[0m";
black="\e[1;30m";
blue="\e[1;34m";
cyan="\e[1;36m";
green="\e[1;32m";
purple="\e[1;35m";
red="\e[1;31m";
white="\e[1;37m";
yellow="\e[1;33m";

Assuming these are supposed to be Linux console escapes, they can be more portably written thus:

reset="$(tput sgr0)"
lineColor="$reset"
black="$(tput bold; tput setaf 0)"
blue="$(tput bold; tput setaf 4)"
cyan="$(tput bold; tput setaf 6)"
green="$(tput bold; tput setaf 2)"
purple="$(tput bold; tput setaf 5)"
red="$(tput bold; tput setaf 1)"
white="$(tput bold; tput setaf 7)"
yellow="$(tput bold; tput setaf 3)"

The above produces real terminal escapes, so you'll be able to drop the non-POSIX -e flag to echo. That's a Good Thing, but you will need to properly quote their expansions.


In GETCOLOR, where these codes are interpolated, there's a very repetitive switch statement:

 case $match in
 "+black+") lineColor=$black;;
 "+red+") lineColor=$red;;
 #....
 esac

It looks like it would be easier to just substitute the variable name, using ${! }:

function GETCOLOR() {
 if [[ 1ドル =~ \+[a-Z]+\+? ]]
 then
 local match="${BASH_REMATCH[0]}"
 case "$match" in
 +black+|+red+|+green+|+blue+|+purple+|+cyan+|+yellow+|+white+)
 match="${match//+}"
 lineColor="${!match}"
 ;;
 *)
 lineColor="$reset"
 ;;
 esac
 fi
}

That can be simplified further, by using a capture group for the word inside +...+:

function GETCOLOR() {
 if [[ 1ドル =~ \+([a-Z]+)\+? ]]
 then
 local match="${BASH_REMATCH[1]}"
 case "$match" in
 black|red|green|blue|purple|cyan|yellow|white)
 lineColor="${!match}"
 ;;
 *)
 lineColor="$reset"
 ;;
 esac
 fi
}
answered Mar 20, 2017 at 9:59
\$\endgroup\$
2
  • \$\begingroup\$ Excellent response. I updated the Github Project per your suggestions. \$\endgroup\$ Commented Mar 22, 2017 at 5:24
  • \$\begingroup\$ I followed your link - there's a few more places where echo -e is still used, but the -e is no longer needed. And "($echo -e something)" can simplify to "something" for header and footer. \$\endgroup\$ Commented Mar 22, 2017 at 8:47

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.