Programming/Bash: Difference between revisions
Brodriguez (talk | contribs) (Add note about @ variable) |
Brodriguez (talk | contribs) (Move unittesting contents to new page) |
||
(3 intermediate revisions by the same user not shown) | |||
Line 228: | Line 228: | ||
# Outputs "/home/user/" | # Outputs "/home/user/" | ||
${file_name%%my_dir/*} | ${file_name%%my_dir/*} | ||
== Unit Testing == | |||
See [[Programming/Bash/Unit Testing|Unit Testing]]. |
Latest revision as of 20:58, 25 October 2020
Bash is primarily a Linux scripting language, but it works on all versions of Windows as well, if used through git.
File Start
Unless you have explicit reason for otherwise, essentially all bash files can safely start with the line:
#!/usr/bin/env bash
It essentially tells your script what interpreter to use when executing the file.
Comments
Inline Comments
# This is an inline comment.
Block Comments
Block level comments don't truly exist in Bash.
However, there is a hackish way to implement them anyways, according to https://stackoverflow.com/a/43158193
: ' This is a block comment. Comment line 2. Another block comment line. '
Variables
For variable definition, note that spacing is important. Spacing around the equals sign will break the assignment.
Variable Definition
a_bool=true b_bool=false my_var_1="This is " my_var_2="a string."
Variable Usage
In bash, there is an optional bracket ${}
syntax. It's recommended to use when using a variable alongside other values, on a single line.
Below is an example of both minimal syntax and ${my_var}
syntax.
echo "Printing variable values." echo $a_bool echo $b_bool echo ${my_var_1}${my_var_2}
Local Variables
By default, any variable in a bash script is a global variable.
To limit a variable to local scope, use the local syntax.
For example, below defines two variables with a value of "5". One is global and one is local:
my_global_var=5 local my_local_var=5
Passing Variables into the Script
It's possible to pass variables directly from the command line into a given bash script. To do this, type the command to execute the script, followed by all the args you wish to pass in.
For example, if your script name is my_script.sh
, then you might have the following:
./my_script.sh test 5
This will pass in the arguments of "test" and "5" into your script.
Accessing Variables Passed into the Script
You access passed variables via the dollar sign, followed by the argument number.
For example, in the above scenario, we passed in values "test" and "5" as the first and second arg respectively. To access them, we could use:
echo $0 # Prints out our script name, "my_script.sh". echo $1 # Prints out "test". echo $2 # Prints out "5".
You can also get all passed variables in array format, with the ${@}
variable.
If Statements
Basic If
if [[ $x == $y ]] then # Logic if true. fi
Full If
if [[ $x == $y ]] then # Logic for "if" true. elif [[ $x && ($y || $z) ]] then # Logic for "else if" true. else # Logic for false. fi
File and Folder Checks
For a full list of built-in args to check file and folder status, see https://www.gnu.org/software/bash/manual/bash.html#Bash-Conditional-Expressions
For Loops
for <loop_variable> in $<my_iterable_object> do # Logic to execute on each loop. done
For example:
for item in $my_list do echo $item done
Functions
function <function_name> () { # Function logic here. }
Passing Parameters
Passing variables into functions in Bash is a bit...obtuse, for lack of a better word.
Essentially, each function is almost treated as a new instance of a bash script. So functions use the same syntax to pass variables into the script.
For example, if we have test_function and we want to pass two variables, then the code may look like this:
function test_function () { var_1=$1 var_2=$2 }
To call this function, we would have code like this:
some_var_1="test" some_var_2=5 ... test_function $some_var_1 $some_var_2
Data Structures
Arrays
Arrays are one of the most common data structures. See Arrays for more info.
Arrays in Bash are a bit strange, syntactically. For an in-depth explanation, see [1].
Having said that, Bash arrays start at the 0 index. And they can hold elements of different types.
Declaring Arrays
Declare an array by normal variable declaration, with the a list of values between two parenthesis. Note that the list items should only be separated by spaces, with no commas between.
my_array=(1 2 3 4 5)
Accessing Array Values
Arrays in Bash are one of the only variable types that require the bracket syntax.
To append new index values, use:
my_array+=<value>
To read all values in the array, use:
${my_array[@]}
To read a single index, use:
${my_array[<index>]}
To update a single index, use:
my_array[<index>]=<value>
Bash arrays aren't meant to be mutable, and thus don't really have a good way to remove an index. The best alternative is to create a second array that only has the values you want.
Dictionaries
Dictionaries can be incredibly powerful. See Dictionaries for more info.
Declaring Dictionaries
Dictionaries in Bash are called "associative arrays" and are declared with the following:
declare -A my_dict
Accessing Dictionary Values
To set new key-value pairs, use:
# Set multiple key-value pairs. my_dict=( [<key_1>]=<value_1> [<key_2>]=<value_2> ) # Set a single key-value pair. my_dict[<key>]=<value>
To read all key-value pairs, use:
# Expand all keys in pair. ${!my_dict[@]} # Expand all values in pair. ${my_dict[@]}
To read a value in a key-value pair, use:
${my_dict[<key>]}
To update an existing key-value pair, use
my_dict[<key>]=<value>
Bash arrays aren't meant to be mutable, and thus don't really have a good way to remove an index. The best alternative is to create a second array that only has the values you want.
String Manipulation
See https://stackoverflow.com/a/14703709
With bash, it's possible to dynamically trim strings, based on regex matches.
The syntax is:
# Trim shortest match from beginning. ${<string_value>#<regex>} # Trim longest match from beginning. ${<string_value>##<regex>} # Trim shortest match from end. ${<string_value>%<regex>} # Trim longest match from end. ${<string_value>%%<regex>}
For example, if you have a string of
file_name="/home/user/my_dir/my_dir/my_file.tar.gz"
Then you can do the following manipulations:
# Get the full file extension. # Outputs "tar.gz" ${file_name#*.} # Get the last part of the file extension. # Outputs "gz" ${file_name##*.} # Get the full file name, including file extension. # Outputs "my_file.tar.gz" echo "b: ${file_name##*/} # Get parent of current directory. # Outputs "/home/user/my_dir/" ${file_name%my_dir/*} # Get grandparent of current directory. # Outputs "/home/user/" ${file_name%%my_dir/*}
Unit Testing
See Unit Testing.