Shell
Bash
Bourne Again SHell, is also a language
- How to run a bash script:
bash /path/to/scriptchmod +x /path/to/scriptthen/path/to/script(requires shebang)
Script
Parameter
$1~$9,${10}…: Parameters$@: All parameters (independent)$*: All parameters (catenate as one string)$#: The number of parameters$?: Return value of last command$$: PID of this shell$!: PID of latest background process$_: The last parameter of last command$-: This shell’s options
Comments
- Comments: Starts with ”#”
- Shebang: A special comment that specifies that the file is a script and calls a certain interpreter, e.g. bash, python.
#!/bin/bash#!/usr/bin/python
Variable
NAME="value"
echo "$NAME"- Whitespace matters! NO SPACE!!!
- Use
$VAR, or${VAR}(preferred) to output the value of the variableVAR - Variable in bash is untyped
- Operations are contextual
- Everything is string
Use expr command or $(()) (better way) to evaluate expressions.
FOO=1
expr $FOO + 1 # 2
expr $FOO+1 # 1+1
echo $((FOO + 1)) # 2
echo $((FOO+1)) # 2Use the read command to get user input, -p is for optional prompt (Not supported by zsh, use echo -n instead)
read -p "send: " FOO
echo "send: $FOO"Subshell: Use $() evaluate the command inside it and substitute the output into the script.
BAR=$(ls)
echo "$BAR"Conditional
test, synonymous with [], could evaluate an expression and set exit status ($?) to:
- 1 (false)
- 0 (true)
Comparison:
-eq:==-ne:!=-gt:>-lt:<-ge:>=-le:<=
a=10
b=2
[ "$a" -le "$b" ] # false
[[ "$a" <= "$b" ]] # true (String)
(( a <= b )) # falseNote
[ ... ]: A command: POSIX test, the oldest one.[[ ... ]]: Modern shell condition keyword, support regex (=~)(( ... )): Expression evaluation,$?will be set as 0 (true) if outcome is not 0
Boolean operations:
&&and||for shell-a(and) and-o(or) fortest([])
false || echo "Oops, fail"
# Oops, fail
true || echo "Will not be printed"
#
true && echo "Things went well"
# Things went well
false && echo "Will not be printed"
#
true ; echo "This will always run"
# This will always run
false ; echo "This will always run"
# This will always run(false is a command always returning 1 and true is a command always return 0)
[ 0 -le 1 ] && [ 0 -gt 1 ]; echo $?
# 1
[ 0 -le 1 -o 0 -gt 1 ]; echo $?
# 0 if statement:
if [ $1 -lt 0 ]; then
echo "$1 is less than 0"
elif [ $1 -eq 0 ]; then
echo "$1 is equal to 0"
else
echo "$1 is greater than 0"
ficase statement: Use to pattern match
case $1 in
Mon|Tue|Wed|Thu|Fri)
echo "Weekday..."
;;
Sat|Sun)
echo "Weekend!!!"
;;
*)
echo "Invaild"
esacLoops
Array:
my_array=(apple banana cherry)
for loop:
SHEEP=("one" "dos" "tre")
for S in $SHEEP; do
echo "$S sheep..."
doneIn fact, for can also traverse a string with $IFS as delimiter.
- With index:
n=0
for x in {1..10}; do
n=$(($x + $n))
done
echo $nwhile loop:
while true; do
echo "yes"
doneTo read a file by lines:
while IFS= read -r line; do
echo "$line"
done < input.txtNote
VAR=value command arguments
VARwill only affect the command behind it.
Function
function greet() { # () is optional.
echo "Hello, $1!"
}
greet "World"Functions has its own environment but a subtle difference: $1 in function will be the argument passed in the function, not the global one (the argument passed in the script), even if function is called without argument.
functionis a keyword not supported by POSIX which couldreturnan integer and use$FUNCNAMEaccess function’s name, but withoutfunctionkeyword,()is required.localcan declare a variable in the field of function.
Stream
-
>: Output to somewhere else, like a text file. (If there’s anything in the file before, it will be overwritten!)echo "Hello, Wolrd!" > out.txt
-
>>: Append output to a file. It works same as>if file is empty or not exist.echo "Goodbye, Wolrd!" >> out.txt
-
<: Take input from a filecmd < in.txt
-
Pipes (
|): Take output of first command as the input of second command, connectingstdinandstdout.cmd1 | cmd2- It will create a subshell for every command!
-
Process substitution (
<(command)): Simulate the output of command as a file, so it will not create subshell.- Place the output in a temporary file and substitute the
<()with that file’s name. - Handy when a command need a file as argument or input from files instead of
stdin.
- Place the output in a temporary file and substitute the
-
stdin: 0 -
stdout: 1 -
stderr: 2
Redirection: 2>&1, redirecting stderr to stdout (If stdout is also redirected, stderr will also redirect to where stdout is redirected to). So sequence matters.
E.g.
ping -c google.com > /dev/null 2>&1stdout → /dev/null;
stderr → stdout (→ /dev/null)
ping -c google.com 2>&1 > /dev/nullstderr → stdout → terminal
stdout → /dev/null
Some common situation
- Discard
stdout:command > /dev/null - Discard
stderr:command 2> /dev/null - Discard both:
command > /dev/null 2>&1 - Output together (and use pipe to deal with):
command 2>&1 | grep error
Useful Tools/Commands
sedawk