#!/bin/bash # # Author: Georg Voell - georg.voell@standby.cloud # Version: @(#)select-table 3.2.0 12.08.2024 (c)2024 Standby.cloud # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ # # This script can be used free of charge. Use it as is or customize as needed. It is not guaranteed to be # error free and you will not be reimbursed for any damage it may cause. # #@ Reads a tab separated file and pretty prints it and ask user to select a value. #@ #@Usage: select-table [options] filename resultname #@ Options: #@ -h, --help : Displays helptext. #@ -v, --version : Displays the version of the script. #@ -g, --green : If is the same as column, display it green. #@ -y, --yellow : If is the same as column, display it yellow. #@ -r, --red : If is the same as column, display it red. #@ -m, --multiselect : Not yet implemented. #@ -p, --page : Use pagination. Diplay only of lines. #@ Filename: A file with tab separated content. #@Resultname: A file with selected values. #@ #@Examples: #@ printf "cmd\tvers\tos\njq\t1.6\tlinux\nrclone\t1.51.0\tlinux\n" > file.tmp #@ Creates a tab separated value file. #@ select file.tmp result.tmp #@ #@ sel cmd vers os #@ --- ------ ------ ----- #@ 001 jq 1.6 linux #@ 002 rclone 1.51.0 linux #@ #@ Please select a number between 1 and 2 or 'q' to quit: # # Exit codes: # 01: Unknown or wrong parameter. # 02: File is empty. # 03: No value selected. # 04: Error while writing to result file. # 99: User interrupt. # # See also: # **print-header**(1), **install-scripts**(1) # # Update history: # # V 3.0.0 21.04.2021 New version # V 3.1.0 05.06.2023 New copyright # V 3.2.0 12.08.2024 New minor version # # Find executable bash library and source it lib=`which lib.bash 2>/dev/null | sed 's|^no 'lib.bash' in .*||'` if [ "$lib" != "" ]; then source "$lib" else progdir=`dirname "$0"` if [ -r "${progdir}/lib.bash" ]; then source "${progdir}/lib.bash" else echo "Unexpected error: Unable to locate bash library 'lib.bash'." exit 1 fi fi # Do extra cleanup function ExtraCleanup() { filecheck -rm ${scratchfile}.org filecheck -rm ${scratchfile}.wrk } # Check if string is a number and within min and max function CheckNumber() { local number=${1} local min=${2} local max=${3} local result="" result=`echo "$number" | grep '^[0123456789]*$'` if [ "$result" = "" ]; then echo "" else if [ "$min" != "" ]; then if [ $number -lt $min ]; then number="" fi fi if [ "$max" != "" ]; then if [ "$number" != "" ]; then if [ $number -gt $max ]; then number="" fi fi fi echo "$number" fi } function Select() { local result="" local lstart=0 local lend=0 local stat=0 if [ $pagination -gt 0 ]; then lstart=1 lend=$pagination else lstart=1 lend=$max fi while [ "$result" = "" ]; do if [ $pagination -gt 0 ]; then printf "\nPage: $page\n\n" echo "$header" > $scratchfile cat ${scratchfile}.wrk | sed -n "${lstart},${lend}p" >> $scratchfile else printf "\n" echo "$header" > $scratchfile cat ${scratchfile}.wrk >> $scratchfile fi print-table --import $scratchfile $redstr $yellowstr $greenstr if [ $pagination -gt 0 ]; then if [ $page -eq 1 ]; then printf "\nPlease select a number between ${lstart} and ${lend}, 'n' for next page or 'q' to quit: " else if [ $lend -eq $max ]; then printf "\nPlease select a number between ${lstart} and ${lend}, 'b' for back or 'q' to quit: " else printf "\nPlease select a number between ${lstart} and ${lend}, 'n' for next page, 'b' for back or 'q' to quit: " fi fi else printf "\nPlease select a number between ${lstart} and ${lend} or 'q' to quit: " fi # Read input from user read inp if [ $pagination -gt 0 ]; then if [ $page -eq 1 ]; then if [ $lend -lt $max -a "$inp" = "n" -o "$inp" = "next" ]; then lstart=$(($page * $pagination + 1)) let page++ lend=$(($page * $pagination)) if [ $lend -gt $max ]; then lend=$max fi inp="" fi else if [ "$inp" = "b" -o "$inp" = "back" ]; then let page-- lstart=$(($page * $pagination - $pagination + 1)) lend=$(($page * $pagination)) inp="" else if [ $lend -lt $max -a "$inp" = "n" -o "$inp" = "next" ]; then lstart=$(($page * $pagination + 1)) let page++ lend=$(($page * $pagination)) if [ $lend -gt $max ]; then lend=$max fi inp="" fi fi fi fi if [ "$inp" = "q" -o "$inp" = "quit" ]; then result="quit" stat=3 else if [ "$inp" != "" ]; then result=`CheckNumber "$inp" "${lstart}" "${lend}"` if [ "$result" != "" ]; then # sed -n '2p' < file.txt # will print 2nd line # sed -n '2011p' < file.txt # 2011th line # sed -n '10,33p' < file.txt # line 10 up to line 33 # sed -n '1p;3p' < file.txt # 1st and 3th line let result++ cat ${scratchfile}.org | sed -n "${result}p" > $resultfile stat=$? if [ $stat -gt 0 ]; then stat=4 fi else printf "Invalid input '$inp'.\n" fi fi fi done return $stat } # Preset page=0 pagination=0 filename="" resultfile="" redstr="" greenstr="" yellowstr="" header="" # Check parameters: Loop until all parameters are used up while [ $# -gt 0 ]; do pname=${1} case "$pname" in -v | --version) shift showversion=true ;; -h | --help) shift showhelp=true ;; -p | --page) shift if [ "$1" != "" ]; then pagination=`CheckNumber "${1}" "1" "100"` if [ "$pagination" = "" ]; then errstr="Please specify a number between 1 and 100 after parameter '$pname'." fi shift else errstr="Please specify a number after parameter '$pname'." fi ;; -r | --red) shift if [ "$1" != "" ]; then redstr="$pname ${1}" shift else errstr="Please specify a string after parameter '$pname'." fi ;; -g | --green) shift if [ "$1" != "" ]; then greenstr="$pname ${1}" shift else errstr="Please specify a string after parameter '$pname'." fi ;; -y | --yellow) shift if [ "$1" != "" ]; then yellowstr="$pname ${1}" shift else errstr="Please specify a string after parameter '$pname'." fi ;; *) shift paramck=`echo "$pname" | grep '^-'` # Keys don't begin with '-' if [ "$paramck" != "" ]; then errstr="Unknown option '$pname'." else if [ "$filename" = "" ]; then filename="$pname" else if [ "$resultfile" = "" ]; then resultfile="$pname" else errstr="Unknown additional parameter: '$pname'." fi fi fi esac done # Check if filename is empty and file exists if [ "$resultfile" = "" ]; then errstr="Please specify a file for output." else if [ "$filename" = "" ]; then errstr="Please specify a file with Tab separated values." else if [ ! -f "$filename" ]; then errstr="File '$filename' does not exists." fi fi fi # Display help or error message DisplayHelp ### Main # Create a workfile without empty lines grep . "$filename" > ${scratchfile}.org result=`filecheck -sl ${scratchfile}.org` if [ "$result" = "" ]; then errormsg 2 "($progstr) File contains lesss then 2 lines. Exiting." filecheck -rm ${scratchfile}.org exit 2 fi i=0 while read line; do if [ $i -eq 0 ]; then header=`printf "sel\t%s\n" "$line"` else printf "%03d\t%s\n" $i "$line" >> ${scratchfile}.wrk fi let i++ done < ${scratchfile}.org max=$(($i - 1)) # Number of lines in file if [ $max -le $pagination ]; then pagination=0 else page=1 fi Select exitcode=$? # Cleanup and exit Cleanup exit $exitcode