跳到主要内容

Shell

OS

Unix

  • Bash
  • Zsh

Windows

Mac OS X

  • Bash

Tools

  • shellcheck
  • makeself

Invocation

Restricted Shell

Login Shell

echo $0
-bash
  • /etc/profile
  • ~/.bash_profile
  • ~/.bash_login
  • ~/.profile
  • ~/.bash_logout

Non-Login Shell

echo $0
bash
  • /etc/bash.bashrc
  • ~/.bashrc

Interactive Shell

Non-Interactive Shell

SH

POSIX

Bash Options

set(POSIX)

  • set -o vi/set -o emacs

shopt

SubShell

SubShellNon-SubShell
(){}
|

Reserved Words

  • function/{}
  • if/then/elif/else/fi
  • while/until/for/in/do/done
  • case/esac
  • select
  • [[]]/!
  • coproc
  • time

Control Operator

  • ||
  • &&
  • &
  • ;
  • ;;
  • ;&
  • ;;&
  • |
  • |&(2>&1)
  • (
  • )

Quoting

  • Escape Character
    • \(backslash)
  • Single Quotes
  • Double Quotes
  • ANSI-C Quoting(man echo)

Comment

CommentDescription
#one-line comment
:' \n This is a \n multi line comment \n 'multiple lines comment

Internal Variables

VariableComment
$N($0,$1,$2)Positional parameters, passed from command line to script, passed to a function, or set to a variable
$#Number of command-line arguments or positional parameters
#*All of the positional parameters, seen as a single word
$@Same as $*, but each parameter is a quoted string, that is, the parameters are passed on intact, without interpretation or expansion. This means, among other things, that each parameter in the argument list is seen as a separate word
$?Exit status of a command, function, or the script itself
$!PID (process ID) of last job run in background
$$PID of shell
$_Special variable set to final argument of previous command executed

Constructs

Sequence

Loop

# Keywors: until while for break continue

# Basic for loop
for i in /etc/rc.*; do
echo $i
done

# C-like for loop
for ((i = 0 ; i < 100 ; i++)); do
echo $i
done

# Ranges
for i in {1..5}; do
echo "Welcome $i"
done

for i in {5..50..5}; do
echo "Welcome $i"
done

# Reading lines
cat file.txt | while read line; do
echo $line
done

# Forever
while true; do
···
done

Conditionals

# Test
[[ -z STRING ]] # Empty string
[[ -n STRING ]] # Not empty string
[[ STRING == STRING ]] # Equal
[[ STRING != STRING ]] # Not Equal
[[ NUM -eq NUM ]] # Equal
[[ NUM -ne NUM ]] # Not equal
[[ NUM -lt NUM ]] # Less than
[[ NUM -le NUM ]] # Less than or equal
[[ NUM -gt NUM ]] # Greater than
[[ NUM -ge NUM ]] # Greater than or equal
[[ STRING =~ STRING ]] # Regexp
(( NUM < NUM )) # Numeric conditions
# File
[[ -e FILE ]] # Exists
[[ -r FILE ]] # Readable
[[ -h FILE ]] # Symlink
[[ -d FILE ]] # Directory
[[ -w FILE ]] # Writable
[[ -s FILE ]] # Size is > 0 bytes
[[ -f FILE ]] # File
[[ -x FILE ]] # Executable
[[ FILE1 -nt FILE2 ]] # 1 is more recent than 2
[[ FILE1 -ot FILE2 ]] # 2 is more recent than 1
[[ FILE1 -ef FILE2 ]] # Same files
# More conditions
[[ -o noclobber ]] # If OPTIONNAME is enabled
[[ ! EXPR ]] # Not
[[ X && Y ]] # And
[[ X || Y ]] # Or

# Keywors: if case select
if [[ -z "$string" ]]; then
echo "String is empty"
elif [[ -n "$string" ]]; then
echo "String is not empty"
fi

# case
case "$1" in
start | up)
vagrant up
;;

*)
echo "Usage: $0 {start|stop|ssh}"
;;
esac

Return/Exit

  • return
  • exit

Expansion

  • Brace

    {A,B}.js
    {1..5}
  • Parameter

    name="John"
    echo ${name}
    echo ${name/J/j} #=> "john" (substitution)
    echo ${name:0:2} #=> "Jo" (slicing)
    echo ${name::2} #=> "Jo" (slicing)
    echo ${name::-1} #=> "Joh" (slicing)
    echo ${name:(-1)} #=> "n" (slicing from right)
    echo ${name:(-2):1} #=> "h" (slicing from right)
    echo ${food:-Cake} #=> $food or "Cake"

Data Type

String

Number

Arrays

Fruits=('Apple' 'Banana' 'Orange')
Fruits[0]="Apple"
Fruits[1]="Banana"
Fruits[2]="Orange"

echo ${Fruits[0]} # Element #0
echo ${Fruits[-1]} # Last element
echo ${Fruits[@]} # All elements, space-separated
echo ${#Fruits[@]} # Number of elements
echo ${#Fruits} # String length of the 1st element
echo ${#Fruits[3]} # String length of the Nth element
echo ${Fruits[@]:3:2} # Range (from position 3, length 2)
echo ${!Fruits[@]} # Keys of all elements, space-separated

for i in "${arrayName[@]}"; do
echo $i
done

Dictionary

declare -A sounds
sounds[dog]="bark"
sounds[cow]="moo"
sounds[bird]="tweet"
sounds[wolf]="howl"

echo ${sounds[dog]} # Dog's sound
echo ${sounds[@]} # All values
echo ${!sounds[@]} # All keys
echo ${#sounds[@]} # Number of elements
unset sounds[dog] # Delete dog

for val in "${sounds[@]}"; do
echo $val
done

for key in "${!sounds[@]}"; do
echo $key
done

IO

Input

Here Document

cat << EOF
#!/usr/bin/env bash
true
EOF

Here String

# <<< = |

read FIRST SECOND <<< "Hello World"
echo "Hello World" | read FIRST SECOND # read run in subshell

Output

Process

  • Parallel
  • xargs

History

CommandDescription
!!Execute last command again
!$Expand last parameter of most recent command
!*Expand all parameters of most recent command
!Expand most recent invocation of command

Projects

Mindmaps

Reference