mirror of
https://github.com/TrudeEH/web.git
synced 2025-12-06 16:33:37 +00:00
287 lines
6.2 KiB
Markdown
287 lines
6.2 KiB
Markdown
---
|
||
title: Shell Scripting [BASH]
|
||
description:
|
||
summary:
|
||
draft: true
|
||
tags:
|
||
author: TrudeEH
|
||
showToc: true
|
||
---
|
||
|
||
## Bash Language
|
||
|
||
### Strings
|
||
|
||
- `""` Defines a string which supports substitutions (`$` and `\`, for example).
|
||
- `''` Defines a string, but preserves its actual value (substitutions are treated as regular characters).
|
||
- [ANSI Escape Sequences](c-language.md#ANSI%20Escape%20Sequences) apply when using `""`.
|
||
|
||
### Comments
|
||
|
||
```bash
|
||
# comment
|
||
```
|
||
|
||
### Commands
|
||
|
||
A shell command consists of the command itself, followed by its arguments.
|
||
|
||
```bash
|
||
command "arg1" "arg2"
|
||
```
|
||
|
||
If the first word of a command is a reserved word, bash handles the command, otherwise, it searches for an executable on the system's `$PATH`, a list of directories where a binary could be located.
|
||
|
||
#### Reserved Words
|
||
|
||
| | | | | | |
|
||
|---|---|---|---|---|---|
|
||
|`if`|`then`|`elif`|`else`|`fi`|`time`|
|
||
|`for`|`in`|`until`|`while`|`do`|`done`|
|
||
|`case`|`esac`|`coproc`|`select`|`function`|
|
||
|`{`|`}`|`[[`|`]]`|`!`|
|
||
|
||
### List of Commands
|
||
|
||
- `command1 ; command2` Execute command2 after command1, sequentially.
|
||
- `command1 &` Execute command1 asynchronously in a subshell.
|
||
- `command1 && command2` *AND*: Only execute command2 if command1 returns 0 (success).
|
||
- `command1 || command2` *OR*: Only execute command2 if command1 returns a non-zero exit value (failure).
|
||
|
||
### Loops
|
||
|
||
#### `until`
|
||
|
||
```bash
|
||
until test-commands; do
|
||
...
|
||
done
|
||
```
|
||
|
||
Execute the code in `...` for as long as `test-commands` return non-zero.
|
||
|
||
#### `while`
|
||
|
||
```bash
|
||
while test-commands; do
|
||
...
|
||
done
|
||
```
|
||
|
||
Execute `...` for as long as `test-commands` return 0.
|
||
|
||
#### `for`
|
||
|
||
Expand `words` and execute `...` for each member in the resultant list, with `name` bound to the current member.
|
||
|
||
##### Iterate through List
|
||
|
||
```bash
|
||
for item in list; do
|
||
echo $item
|
||
done
|
||
```
|
||
|
||
##### C-like Loop
|
||
|
||
```bash
|
||
for (( i=1; i<=10; i++ )); do
|
||
echo "Loop number:" $i
|
||
done
|
||
```
|
||
|
||
##### Infinite Loop
|
||
|
||
```bash
|
||
for (( ; ; )); do
|
||
echo "Press Ctrl+C to stop..."
|
||
done
|
||
```
|
||
|
||
### Conditional Constructs
|
||
|
||
#### `if`
|
||
|
||
```bash
|
||
if test-commands; then
|
||
...
|
||
elif more-test-commands; then
|
||
...
|
||
else
|
||
...
|
||
fi
|
||
```
|
||
|
||
Execute the first `...` if `test-commands` returns 0, and evaluate the next condition otherwise. This process repeats until `else` is found, or one of the `tests` evaluates to a 0.
|
||
Once any `...` executes, the remaining `if` construct is skipped.
|
||
|
||
#### `case`
|
||
|
||
```bash
|
||
case word in
|
||
p1 | p2 | p3) ... ;;
|
||
p4 | p5 )
|
||
...
|
||
;;
|
||
*) ... ;;
|
||
esac
|
||
```
|
||
|
||
Execute the `...` corresponding to the first pattern (`pX`) that matches the `word`.
|
||
The `|` operator separates multiple patterns, and each clause can end with `;;`, `;&` or `;;&`. It's common to use `*` as the default case, since the pattern will always match.
|
||
|
||
Using `;&` instead of `;;` would cause the next `...` to be executed as well, and `;;&` would test the next clause, instead of immediately exiting.
|
||
|
||
#### `select`
|
||
|
||
```bash
|
||
PS3="Enter a number: "
|
||
|
||
select option in entry1 entry2 entry3 entry4 entry5
|
||
do
|
||
echo "Selected character: $option"
|
||
echo "Selected number: $REPLY"
|
||
done
|
||
```
|
||
|
||
The `select` command generates a menu, displaying each `entryX` in a list. The user is then prompted to select an option (in this case, a number from 1-5), and the resultant `$option` and `$REPLY` are then provided as variables.
|
||
|
||
Output:
|
||
|
||
```
|
||
1) entry1
|
||
2) entry2
|
||
3) entry3
|
||
4) entry4
|
||
5) entry5
|
||
Enter a number:
|
||
```
|
||
|
||
#### `((...))`
|
||
|
||
The arithmetic expression is evaluated according to the rules described below (see [Shell Arithmetic]() TODO link to shell arithmetic).
|
||
|
||
#### `[...](...)`
|
||
|
||
Return a status of 0 or 1 depending on the evaluation of the conditional expression expression. Expressions are composed of the primaries described below in [Bash Conditional Expressions](https://www.gnu.org/software/bash/manual/bash.html#Bash-Conditional-Expressions).
|
||
|
||
#### Combine Expressions
|
||
|
||
- `( expression )` Returns the value of expression. (Can be used to override precedence).
|
||
- `! expression` *NOT* an expression. (`true` if expression is `false`).
|
||
- `exp1 && exp2` *AND* - `true` if both expressions are `true`.
|
||
- `exp1 || exp2` *OR* - `true` if either expressions are `true`.
|
||
|
||
#### Grouping Commands
|
||
|
||
Bash allows for commands to be grouped as a single unit. That way, if the group is redirected, the output of every command in the list is passed to a single stream.
|
||
|
||
- `( list )` Create a subshell (variables created inside it can't be accessed outside).
|
||
- `{ list; }` No subshell is created.
|
||
|
||
### Functions
|
||
|
||
```bash
|
||
fname() {
|
||
...
|
||
}
|
||
|
||
function fname {
|
||
...
|
||
}
|
||
```
|
||
|
||
A function can store a block of code (compound command), so it can be reused by calling its name:
|
||
|
||
```bash
|
||
fname
|
||
```
|
||
|
||
Any variables defined inside the function
|
||
|
||
#### Arguments
|
||
|
||
```bash
|
||
fname() {
|
||
echo $1 $2
|
||
}
|
||
|
||
fname "a" "b"
|
||
```
|
||
|
||
#### Scope
|
||
|
||
```bash
|
||
var1='A'
|
||
var2='B'
|
||
|
||
fname () {
|
||
local var1='C'
|
||
var2='D'
|
||
echo "var1: $var1, var2: $var2" # C, D
|
||
}
|
||
|
||
echo "$var1, var2: $var2" # A, B
|
||
fname # C, D
|
||
echo "var1: $var1, var2: $var2" # A, D
|
||
```
|
||
|
||
Defining a variable inside the function overwrites the global scope. To prevent this, use the `local` keyword.
|
||
|
||
#### `return`
|
||
|
||
```bash
|
||
fname() {
|
||
return 1;
|
||
}
|
||
|
||
fname
|
||
echo $? # 1
|
||
```
|
||
|
||
Use the `return` command to exit the function and return a value.
|
||
|
||
### Variables (Parameters)
|
||
|
||
```bash
|
||
name="Trude"
|
||
echo $name # Trude
|
||
|
||
name+=" EH"
|
||
echo $name # Trude EH
|
||
echo ${name}
|
||
```
|
||
|
||
Variables can be of any type, and grow to any needed size.
|
||
|
||
#### Special Variables
|
||
|
||
- `$*` Expands to every positional parameter: `$1$2$3`.
|
||
- `$@` Expands to every positional parameter, separated by spaces: `"$1" "$2" "$3"`.
|
||
- `$#` Number of positional arguments.
|
||
- `$?` Exit status of last command / pipeline.
|
||
- `$-` Current option flags set by `set`, or by the shell itself.
|
||
- `$$` Process ID of the shell. In a subshell, it expands to the process ID of the parent shell.
|
||
- `$!` Process ID of the latest job placed into the background.
|
||
- `$0` Name of the shell or script.
|
||
|
||
### Shell Expansions
|
||
|
||
#### Brace Expansion
|
||
|
||
```bash
|
||
echo a{d,c,b}e # ade ace abe
|
||
```
|
||
|
||
#### Tilde Expansion
|
||
|
||
- `~` = `$HOME`
|
||
- `~+` = `$PWD`
|
||
- `~-` = `$OLDPWD`
|
||
|
||
#### Shell Parameter Expansion
|
||
|
||
### Builtins ---------------------
|
||
|
||
Bash doesn't come with any programs such as `cat`, `grep` and `ls` by default, for example. Those
|