Bash (scripting, not shell)
Created: 2016-03-25 15:31:50 -0700 Modified: 2022-07-04 15:09:22 -0700
Basics
Section titled Basics- Good Gist here with some general guidelines
- ShellCheck is a script analysis tool for shell scripts
- Safe scripting (e.g. by exiting on any error): reference
- For any of the following, just put a line at the top of the script, e.g. “set -Eeuo pipefail”.
- ↑ In fact, that command is a good start for most Bash scripts to make it work like how you’re used to with most programming languages.
- set -e: exit immediately when a command fails
- set -o pipefail: sets exit code of a pipeline (piped commands) to the rightmost failing command
- set -u: treat unset variables as an error and exit immediately
- set -x: print every command before executing it. It’s like Batch’s “@echo on”
- For any of the following, just put a line at the top of the script, e.g. “set -Eeuo pipefail”.
- .bash_profile vs. .bashrc (reference, reference for zsh): in short: bash_profile is for commands that should only run once (like setting your $PATH), bashrc is good for commands that should run every time you start a new shell.
- Interactive vs. login shell (reference): in short: a login shell is when you logged into the system through a shell, e.g. SSHing into a machine. An interactive shell is like when you start a new terminal on macOS.
- Check if a command was successful (reference)
You can also do this
- Return
- “return” isn’t required from all functions
- Arguments
- Reading script-level arguments is the same as reading function-level arguments: 2, etc.
- I find it nice to name arguments in functions anyway:
- Comparing arguments is easy
- Checking if an argument is empty (reference)
-
To pass in an empty argument, specify open and closing quotation marks like this:
- ./foo.sh "" second_arg "" fourth_arg
-
Using temporary buffers
Suppose you have sounds.json like this:
You can modify REPLACE_ME without having to make a temporary file by using a temporary buffer:
↑ [09:24] Pneumatus: that sed command in the temporary buffers section, you know there’s an ‘-i’ arg to sed that lets you do in-place replacement? :)
[09:25] Pneumatus: sed -i ‘s/REPLACE_ME/ribbit/g’ sounds.json
[09:25] Pneumatus: or maybe the other way round
- If/elif/end
Helpful snippets
Section titled Helpful snippets- Set error handling: set -Eeuo pipefail
- This was mentioned earlier, but it makes your environment more like a programming environment.
- Write to stderr and then exit (reference)
This is useful for doing something like:
Section titled This is useful for doing something like:echo ’ || die “Numeric argument required, $1 provided”
Evaluating a scripting expression
Section titled Evaluating a scripting expressionYou’re supposed to use $():
cur_date = $(date)
It used to be that you’d use backticks, e.g.
cur_date=date
(do not use this since it’s deprecated)
Evaluating an arithmetic expression (reference)
Section titled Evaluating an arithmetic expression (reference)Simple example:
For floating-point calculations, use bc.
[14:22] woodworker_: so {varname} is for using variable names when you do not have spaces so you can do {VAR2}
So: (echo $VAR)
“test”
Section titled “test””[ … ]” is syntactic sugar for the “test” command, meaning if you’re having problems with it, you can look through “man test”. Example usage:
Accessing your bash_profile functions from a script
Section titled Accessing your bash_profile functions from a scriptThe best way I found was just to add “source ~/.bash_profile” to the top of whatever script you’re writing, e.g.:
~/.bash_profile:
#!/bin/bash
function foo() {
echo hi
}
test.sh:
#!/bin/bash
source ~/.bash_profile
foo
Using ssh-agent from within bash (notes reference, GitHub reference)
Section titled Using ssh-agent from within bash (notes reference, GitHub reference)(just look at the references)
Section titled (just look at the references)Using “sudo” inside of a script
Section titled Using “sudo” inside of a scriptDon’t do something like this:
sudo -iu bldeploy
<some command that expects to be bldeploy>
Instead, do this:
run_as_bldeploy.sh
Section titled run_as_bldeploy.shsudo -u bldeploy impl.sh
impl.sh
Section titled impl.sh<some command that expects to be bldeploy>
If you really wanted, you could follow the advice from here and do something like “sudo bash -c ‘cmd1; cmd2; cmd3’“. That link also has advice for using ‘here’ documents.
Regex
Section titled RegexI had a string like this: <a bunch of garbage><a href=“http://127.0.0.1:8000/show/df8cd949661a”\>
I got the hash at the end by doing this:
if [[$curlOutput =~ show([a-zA-Z0-9]+)]]; then
bpasteHash=${BASH_REMATCH[1]}
else
echo “No match found”;
fi
The key was not using “w” like you have in other languages. I don’t think that works in Bash to represent a letter character.