-1

I am writing a central script, which acts as a menu driven cli through which I trigger other scripts based on the input.

#!/bin/bash

echo "Server Name - `hostname`"
echo "-------------------------------"
echo "     M A I N - M E N U"
echo "-------------------------------"
echo "1. init"
echo "2. insert"
echo "3. show"
echo "4. update"
echo "5. rm"
echo "6. ls"
echo "7. shutdown -> shutdown the server"

while :
do
    printf '> '
    read -r varname
    set -- $varname

    case $1 in
        init)
            ./init.sh $2
            echo $status
            ;;
        insert)
            ./insert.sh $2 $3 '' $4
            ;;
        show)
            ./show.sh $2 $3
            ;;
        update)
            ./insert.sh $2 $3 'f' $4
            ;;
        rm)
            ./rm.sh $2 $3
            ;;
        ls)
            ./ls.sh $2 $3
            ;;
        shutdown)
            exit 0
            ;;
        exit)
            exit 0
            ;;
        *)
            #echo "Error: Bad request"
            ;;
    esac

done

Current:

I have purposefully added the print '> ' statement so as to get an interactive interface just like node cli.

insert user1 google 'login:blahblah@gmail.com\npass:blah'

  • $1 is insert
  • $2 is user1
  • $3 is google
  • $4 is 'login:blahblah@gmail.com\npass:blah'

Expected:

I wish to read arguments the same way we pass arguments when we run a script.

Ex:

sh add.sh 10 20 or sh add.sh "10" "20"

Either way when we read $1 or $2 in the add shell script, we will be getting 10 and 20 as their values.

insert user1 google 'login:blahblah@gmail.com\npass:blah'

  • $1 is insert
  • $2 is user1
  • $3 is google
  • $4 is login:blahblah@gmail.com\npass:blah

I do not want to get the input and then remove the trailing quotes. I would like to have the exact behaviour when we run a script and pass arguments.

PS: Please suggest how to get a cli just like node too which has access to previously run commands using the Up arrow.

Thanks in advance

Ashwath
  • 61
  • 7
  • Possible duplicate of [What are the special dollar sign shell variables?](https://stackoverflow.com/q/5163144/608639), [What do $? $0 $1 $2 mean in shell script?](https://stackoverflow.com/q/29258603/608639), [Read a variable in bash with a default value](https://stackoverflow.com/q/2642585/608639), [How to read user input into a variable in Bash?](https://stackoverflow.com/q/18544359/608639), etc. – jww Nov 03 '19 at 12:50
  • the referred links do not answer my question. I am aware about the above mentioned information. Please try to answer my question. – Ashwath Nov 03 '19 at 13:25
  • I would like to read arguments just like a shell script execution reads its arguments using $1, $2, but from inside a script. I have explained how things differ and the expected results. – Ashwath Nov 03 '19 at 13:32

1 Answers1

1

The central idea here seems to revolve around these lines:

    read -r varname
    set -- $varname

The read command reads a whole line of input as literal text (without the possibility of line continuation) and records it as the value of variable varname, then that variable is expanded to provide arguments to the set builtin. But this is not equivalent to presenting the same command line as shell input.

Of particular relevance to the question is that quotation marks arising from variable expansion are not subject to quote removal. Also, brace and tilde expansion happen prior to variable expansion, so they will not be effective for you either.

What you really seem to want is a double expansion. Specifically, this:

eval "set -- $varname"

Do note that eval is very dangerous and subject to exploitation. For example, consider what would happen a user enters this command into your script (which is supposed running with sufficient privilege to perform a system shutdown):

show pwned; rm -rf /*
John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • I am currently doing this. Is there a better way to implement a menu driven CLI? In addition to this please give me suggestions as to how NODE might have implemented its CLI. It has access to previously run commands too. – Ashwath Nov 03 '19 at 13:59
  • What you present in the question is *not* what I have suggested, @Ashwath. The `eval` is key, in that it is what resolves the issues you asked about with argument quoting, as well as several similar issues that you did not ask specifically about. The aspect of the question about history recording is too broad, especially inasmuch as you are asking for speculation about how an entirely different piece of software works. – John Bollinger Nov 03 '19 at 18:13
  • More generally, there is *no* way to implement a "menu-driven CLI", because the term is an oxymoron. "Menu-driven" and "command-line" are two largely separate UI paradigms. Yours would be better described as a CLI with a limited set of commands and verbose prompting. The variation on it that I suggested is the easiest way to obtain command-line parsing with full shell syntax. If it does not serve your purpose -- other than because it's dangerous -- then you'll need to clarify what the issue with it is. – John Bollinger Nov 03 '19 at 18:22