From e44db542c270496799a2da74ac84095a84f707b6 Mon Sep 17 00:00:00 2001 From: thomasabishop Date: Fri, 17 Mar 2023 07:41:38 +0000 Subject: [PATCH] Autosave: 2023-03-17 07:41:38 --- .../Shell/Capturing_user_input_in_Bash.md | 79 +++++++++++++++++++ .../Shell/File_descriptors.md | 2 +- .../Shell/Functions_in_Bash.md | 2 +- ..._arguments_and_options_to_Bash_scripts.md} | 41 ++++++++-- Programming_Languages/Shell/Read.md | 14 +++- 5 files changed, 124 insertions(+), 14 deletions(-) create mode 100644 Programming_Languages/Shell/Capturing_user_input_in_Bash.md rename Programming_Languages/Shell/{Passing_arguments_to_scripts.md => Passing_arguments_and_options_to_Bash_scripts.md} (58%) diff --git a/Programming_Languages/Shell/Capturing_user_input_in_Bash.md b/Programming_Languages/Shell/Capturing_user_input_in_Bash.md new file mode 100644 index 0000000..58fc461 --- /dev/null +++ b/Programming_Languages/Shell/Capturing_user_input_in_Bash.md @@ -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 +``` diff --git a/Programming_Languages/Shell/File_descriptors.md b/Programming_Languages/Shell/File_descriptors.md index ca6c1f1..786252f 100644 --- a/Programming_Languages/Shell/File_descriptors.md +++ b/Programming_Languages/Shell/File_descriptors.md @@ -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. diff --git a/Programming_Languages/Shell/Functions_in_Bash.md b/Programming_Languages/Shell/Functions_in_Bash.md index 67456db..1cf3f0a 100644 --- a/Programming_Languages/Shell/Functions_in_Bash.md +++ b/Programming_Languages/Shell/Functions_in_Bash.md @@ -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() { diff --git a/Programming_Languages/Shell/Passing_arguments_to_scripts.md b/Programming_Languages/Shell/Passing_arguments_and_options_to_Bash_scripts.md similarity index 58% rename from Programming_Languages/Shell/Passing_arguments_to_scripts.md rename to Programming_Languages/Shell/Passing_arguments_and_options_to_Bash_scripts.md index 20916ef..2226b38 100644 --- a/Programming_Languages/Shell/Passing_arguments_to_scripts.md +++ b/Programming_Languages/Shell/Passing_arguments_and_options_to_Bash_scripts.md @@ -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 + +``` diff --git a/Programming_Languages/Shell/Read.md b/Programming_Languages/Shell/Read.md index 05f9615..ec47810 100644 --- a/Programming_Languages/Shell/Read.md +++ b/Programming_Languages/Shell/Read.md @@ -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