Autosave: 2023-03-17 07:41:38
This commit is contained in:
parent
3717dbe7b0
commit
e44db542c2
5 changed files with 124 additions and 14 deletions
79
Programming_Languages/Shell/Capturing_user_input_in_Bash.md
Normal file
79
Programming_Languages/Shell/Capturing_user_input_in_Bash.md
Normal file
|
@ -0,0 +1,79 @@
|
|||
---
|
||||
categories:
|
||||
- Programming Languages
|
||||
tags:
|
||||
- shell
|
||||
---
|
||||
|
||||
# Capturing user input in Bash
|
||||
|
||||
We use [read](/Programming_Languages/Shell/Read.md) to gather user input.
|
||||
|
||||
## Capturing raw inputs
|
||||
|
||||
```bash
|
||||
# Wait for the input
|
||||
echo "What is your name?"
|
||||
read name
|
||||
|
||||
# Silently gather the input and proceed (the input won't show up in the terminal)
|
||||
echo "What is your password?"
|
||||
read -s pass
|
||||
|
||||
# Combine in single line
|
||||
read -p "What's your favourite animal? " animal
|
||||
|
||||
echo name: $name, pass $pass, animal: $animal
|
||||
```
|
||||
|
||||
## Offering a selection
|
||||
|
||||
We can use `select` to get the user to choose from a series of options.
|
||||
|
||||
```sh
|
||||
select animal in "bird" "dog" "cow"
|
||||
do
|
||||
echo "You selected $animal"
|
||||
break
|
||||
done
|
||||
```
|
||||
|
||||
This will present each option as number that can be inputted:
|
||||
|
||||
```
|
||||
1) bird
|
||||
2) dog
|
||||
3) cow
|
||||
#? 1
|
||||
You selected bird
|
||||
```
|
||||
|
||||
We could make this more robust by using a case statement:
|
||||
|
||||
```sh
|
||||
select animal in "bird" "dog" "cow"
|
||||
do
|
||||
case $animal in
|
||||
bird) echo "Birds like to tweet";;
|
||||
dog) echo "Dogs like to woof";;
|
||||
cow) echo "Cows like to moo";;
|
||||
quit) break;;
|
||||
*) "I'm not sure what that means"
|
||||
esac
|
||||
done
|
||||
```
|
||||
|
||||
## Validating the user inputs
|
||||
|
||||
Here we test that the right number of [arguments](/Programming_Languages/Shell/Passing_arguments_and_options_to_Bash_scripts.md) have been passed to the script:
|
||||
|
||||
```sh
|
||||
if (( $#<3 )); then
|
||||
echo "This command requires three arguments:"a
|
||||
echo "username, userId, and favouriteNumber"
|
||||
else
|
||||
echo "username: $1"
|
||||
echo "userid: $2"
|
||||
echo "favourite number: $3"
|
||||
fi
|
||||
```
|
|
@ -17,4 +17,4 @@ File descriptors are shorthand for `stdin`, `stdout` and `stderr`:
|
|||
|
||||
They are typically used when you want to [redirect](/Programming_Languages/Shell/Redirection.md) the output of the standard/input /output/error somewhere, e.g a file or as input to another program. A classic case is `[some_command] > /dev/null 2>&1`
|
||||
|
||||
They are all technically "files" which are open and which append themselves to every process that can run in the shell. For any command or program that you run, you will be able to access `0`, `1` and `2` for them. In this way they are similar to variables like [`$0`](/Programming_Languages/Shell/Passing_arguments_to_scripts.md#passing-arguments) and [`$@`](/Programming_Languages/Shell/Passing_arguments_to_scripts.md#passing-arguments). They have a universal meaning within the context of the shell runtime.
|
||||
They are all technically "files" which are open and which append themselves to every process that can run in the shell. For any command or program that you run, you will be able to access `0`, `1` and `2` for them. In this way they are similar to variables like [`$0`](/Programming_Languages/Shell/Passing_arguments_and_options_to_Bash_scripts.md#passing-arguments) and [`$@`](/Programming_Languages/Shell/Passing_arguments_and_options_to_Bash_scripts.md#passing-arguments). They have a universal meaning within the context of the shell runtime.
|
||||
|
|
|
@ -27,7 +27,7 @@ echo $expandedRange
|
|||
|
||||
## Get all arguments as an array
|
||||
|
||||
We can access all the arguments passed to a function using the `$@` syntax we encountered before when [passing arguments to scripts](/Programming_Languages/Shell/Passing_arguments_to_scripts.md). (Here a function is a kind of script in miniature so the process is the same.)
|
||||
We can access all the arguments passed to a function using the `$@` syntax we encountered before when [passing arguments to scripts](/Programming_Languages/Shell/Passing_arguments_to_Bash_scripts.md). (Here a function is a kind of script in miniature so the process is the same.)
|
||||
|
||||
```sh
|
||||
function numberThings() {
|
||||
|
|
|
@ -5,13 +5,13 @@ tags:
|
|||
- shell
|
||||
---
|
||||
|
||||
# Passing arguments to scripts
|
||||
# Passing arguments and options to Bash scripts
|
||||
|
||||
## Relation between commands and programs
|
||||
|
||||
Whenever we issue a command in bash we are really running an executable program that is associated with the command. This is why when we create our own bash scripts we must run `chmod` to make them executable. When we issue a command like `./file.sh` we are running an executable program.
|
||||
Whenever we issue a command in bash we are running an executable program that the command token references. This is why when we create our own bash scripts we must run `chmod` to make them executable. When we issue a command like `./do_something.sh` we are running an executable program.
|
||||
|
||||
When we run a program like `cd` or `npm` we don’t have to type `./cd.sh` or `./npm.sh`. This is because a reference to the program file is already in our `$PATH`.
|
||||
When we run a program like `cd` or `npm` we don’t have to type `./cd.sh` or `./npm.sh`. This is because a reference to the program file is already in our [`$PATH`](/Programming_Languages/Shell/The_PATH.md).
|
||||
|
||||
In the case of `cd`, this is an in-built program and as such it will be sourced from a binary and we have a reference to the binary in path. In the case of `npm`, this is not an in-built program however in order to run it we must already have it in our `PATH`.
|
||||
|
||||
|
@ -58,9 +58,17 @@ Key points:
|
|||
|
||||
## Passing options
|
||||
|
||||
Options differ from arguments in that they are prepended with `-` and they can be passed in any order. We use the `getops` program to parse options.
|
||||
Options differ from arguments in that they are prepended with `-` and they can be passed in any order. We use the `getops` program to parse the options that the user inputs with their command.
|
||||
|
||||
We can demonstrate this with a script that takes in a username and password as options:
|
||||
We can demonstrate this with a script that takes in a username and password as options.
|
||||
|
||||
We can handle an option-based input like:
|
||||
|
||||
```
|
||||
some-program -u thomas -p password123
|
||||
```
|
||||
|
||||
With the following construct:
|
||||
|
||||
```sh
|
||||
while getopts u:p: option; do
|
||||
|
@ -73,12 +81,29 @@ done
|
|||
echo "user: $user / pass: $pass"
|
||||
```
|
||||
|
||||
With the input `my-option-script.sh -u thomas -p password123` we would get the following returned:
|
||||
Which returns:
|
||||
|
||||
```
|
||||
user: thomas / pass: password123
|
||||
```
|
||||
|
||||
Here we set up a `while` loop to parse the stdin and store it in the variable `option`. We run this through a case statement and individuate each option, storing them in dedicated local variables via the global `$OPTARG` variable
|
||||
Here we set up a `while` loop against the `getopts` command to parse the options in the stdin and store each one in a `option`. We run each `option` through a case statement and individuate each one, storing them in dedicated local variables via the global `$OPTARG` variable
|
||||
|
||||
Note: using a colon after each option means that the script will expect the given option to have a value.
|
||||
### The role of the colons
|
||||
|
||||
Using a colon after each option means that the script will expect the given option to have a value. If we put a colon _before_ each of the options we expect this will allow us to view any option the user provides in our option handler. This is useful when you are working with very many options, as with a command-line program.
|
||||
|
||||
This version demonstrates a more exhaustive use case:
|
||||
|
||||
```sh
|
||||
while getopts :u:p: option; do
|
||||
case $option in
|
||||
u) user=$OPTARG;;
|
||||
p) pass=$OPTARG;;
|
||||
a) echo "got the 'a' flag";;
|
||||
b) echo "got the 'b' flag";;
|
||||
?) echo "Don't know what $OPTARG is!"
|
||||
esac
|
||||
done
|
||||
|
||||
```
|
|
@ -13,11 +13,17 @@ The primary use of `read` is to capture user input from `stdin`. It can also be
|
|||
|
||||
## Example of capturing user input
|
||||
|
||||
When we use `read` to gather user input, the script will pause until the input is provided.
|
||||
|
||||
```bash
|
||||
$ read var1 var2
|
||||
$ thomas bishop # user inputs this
|
||||
$ echo $var2
|
||||
$ bishop
|
||||
echo "What is your name?"
|
||||
read name
|
||||
|
||||
echo "What is your password?"
|
||||
read -s pass
|
||||
|
||||
read
|
||||
|
||||
```
|
||||
|
||||
> If you don't specify variables, `read` will automatically parse using whitespace
|
||||
|
|
Loading…
Add table
Reference in a new issue