Shell手册 Jul 5, 2020 · shell · 分享到: Getting started Example Variables String quotes Shell execution Conditional execution Functions Example Conditionals example Strict mode Brace expansion Parameter expansions Basics Substitution Comments Substrings Length Manipulation Default values Loops Basic for loop C-like for loop Ranges With step size Reading lines Forever Functions Defining functions Returning values Raising errors Arguments Conditionals Conditions More conditions File conditions Test Example Arrays Defining arrays Working with arrays Operations Iteration Dictionaries Defining Working with dictionaries Iteration Operation Iterate over values Iterate over keys Options set Options Glob options History Commands Expansions Operation Info Slices Miscellaneous Numeric calculations Subshells Redirection Inspecting commands Trap errors Case/switch Source relative printf Directory of script Getting options Heredoc Reading input Special variables Go to previous directory Check for command's result Grep check Also see Getting started This is a quick reference to getting started with Bash scripting. Learn bash in y minutes (learnxinyminutes.com) Bash Guide (mywiki.wooledge.org) Example 1#!/usr/bin/env bash 2 3NAME="John" 4echo "Hello $NAME!" Variables 1NAME="John" 2echo $NAME 3echo "$NAME" 4echo "${NAME}!" String quotes 1NAME="John" 2echo "Hi $NAME" #=> Hi John 3echo 'Hi $NAME' #=> Hi $NAME Shell execution 1echo "I'm in $(pwd)" 2echo "I'm in `pwd`" 3# Same See Command substitution Conditional execution 1git commit && git push 2git commit || echo "Commit failed" Functions Example 1get_name() { 2 echo "John" 3} 4 5echo "You are $(get_name)" See: Functions Conditionals example 1if [[ -z "$string" ]]; then 2 echo "String is empty" 3elif [[ -n "$string" ]]; then 4 echo "String is not empty" 5fi See: Conditionals Strict mode 1set -euo pipefail 2IFS=$'\n\t' See: Unofficial bash strict mode Brace expansion 1echo {A,B}.js Expression Description {A,B} Same as A B {A,B}.js Same as A.js B.js {1..5} Same as 1 2 3 4 5 See: Brace expansion Parameter expansions Basics 1name="John" 2echo ${name} 3echo ${name/J/j} #=> "john" (substitution) 4echo ${name:0:2} #=> "Jo" (slicing) 5echo ${name::2} #=> "Jo" (slicing) 6echo ${name::-1} #=> "Joh" (slicing) 7echo ${name:(-1)} #=> "n" (slicing from right) 8echo ${name:(-2):1} #=> "h" (slicing from right) 9echo ${food:-Cake} #=> $food or "Cake" 1length=2 2echo ${name:0:length} #=> "Jo" See: Parameter expansion 1STR="/path/to/foo.cpp" 2echo ${STR%.cpp} # /path/to/foo 3echo ${STR%.cpp}.o # /path/to/foo.o 4echo ${STR%/*} # /path/to 5 6echo ${STR##*.} # cpp (extension) 7echo ${STR##*/} # foo.cpp (basepath) 8 9echo ${STR#*/} # path/to/foo.cpp 10echo ${STR##*/} # foo.cpp 11 12echo ${STR/foo/bar} # /path/to/bar.cpp 1STR="Hello world" 2echo ${STR:6:5} # "world" 3echo ${STR: -5:5} # "world" 1SRC="/path/to/foo.cpp" 2BASE=${SRC##*/} #=> "foo.cpp" (basepath) 3DIR=${SRC%$BASE} #=> "/path/to/" (dirpath) Substitution Code Description ${FOO%suffix} Remove suffix ${FOO#prefix} Remove prefix --- --- ${FOO%%suffix} Remove long suffix ${FOO##prefix} Remove long prefix --- --- ${FOO/from/to} Replace first match ${FOO//from/to} Replace all --- --- ${FOO/%from/to} Replace suffix ${FOO/#from/to} Replace prefix Comments 1# Single line comment 1: ' 2This is a 3multi line 4comment 5' Substrings Expression Description ${FOO:0:3} Substring (position, length) ${FOO:(-3):3} Substring from the right Length Expression Description ${#FOO} Length of $FOO Manipulation 1STR="HELLO WORLD!" 2echo ${STR,} #=> "hELLO WORLD!" (lowercase 1st letter) 3echo ${STR,,} #=> "hello world!" (all lowercase) 4 5STR="hello world!" 6echo ${STR^} #=> "Hello world!" (uppercase 1st letter) 7echo ${STR^^} #=> "HELLO WORLD!" (all uppercase) Default values Expression Description ${FOO:-val} $FOO, or val if unset (or null) ${FOO:=val} Set $FOO to val if unset (or null) ${FOO:+val} val if $FOO is set (and not null) ${FOO:?message} Show error message and exit if $FOO is unset (or null) Omitting the : removes the (non)nullity checks, e.g. ${FOO-val} expands to val if unset otherwise $FOO. Loops Basic for loop 1for i in /etc/rc.*; do 2 echo $i 3done C-like for loop 1for ((i = 0 ; i < 100 ; i++)); do 2 echo $i 3done Ranges 1for i in {1..5}; do 2 echo "Welcome $i" 3done With step size 1for i in {5..50..5}; do 2 echo "Welcome $i" 3done Reading lines 1cat file.txt | while read line; do 2 echo $line 3done Forever 1while true; do 2 ··· 3done Functions Defining functions 1myfunc() { 2 echo "hello $1" 3} 1# Same as above (alternate syntax) 2function myfunc() { 3 echo "hello $1" 4} 1myfunc "John" Returning values 1myfunc() { 2 local myresult='some value' 3 echo $myresult 4} 1result="$(myfunc)" Raising errors 1myfunc() { 2 return 1 3} 1if myfunc; then 2 echo "success" 3else 4 echo "failure" 5fi Arguments Expression Description $# Number of arguments $* All positional arguments (as a single word) $@ All positional arguments (as separate strings) $1 First argument $_ Last argument of the previous command Note: $@ and $* must be quoted in order to perform as described. Otherwise, they do exactly the same thing (arguments as separate strings). See Special parameters. Conditionals Conditions Note that [[ is actually a command/program that returns either 0 (true) or 1 (false). Any program that obeys the same logic (like all base utils, such as grep(1) or ping(1)) can be used as condition, see examples. Condition Description [[ -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 More conditions Condition Description [[ -o noclobber ]] If OPTIONNAME is enabled --- --- [[ ! EXPR ]] Not [[ X && Y ]] And `[[ X File conditions Condition Description [[ -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 Test Example 1# String 2if [[ -z "$string" ]]; then 3 echo "String is empty" 4elif [[ -n "$string" ]]; then 5 echo "String is not empty" 6else 7 echo "This never happens" 8fi 1# Combinations 2if [[ X && Y ]]; then 3 ... 4fi 1# Equal 2if [[ "$A" == "$B" ]] 1# Regex 2if [[ "A" =~ . ]] 1if (( $a < $b )); then 2 echo "$a is smaller than $b" 3fi 1if [[ -e "file.txt" ]]; then 2 echo "file exists" 3fi Arrays Defining arrays 1Fruits=('Apple' 'Banana' 'Orange') 1Fruits[0]="Apple" 2Fruits[1]="Banana" 3Fruits[2]="Orange" Working with arrays 1echo ${Fruits[0]} # Element #0 2echo ${Fruits[-1]} # Last element 3echo ${Fruits[@]} # All elements, space-separated 4echo ${#Fruits[@]} # Number of elements 5echo ${#Fruits} # String length of the 1st element 6echo ${#Fruits[3]} # String length of the Nth element 7echo ${Fruits[@]:3:2} # Range (from position 3, length 2) 8echo ${!Fruits[@]} # Keys of all elements, space-separated Operations 1Fruits=("${Fruits[@]}" "Watermelon") # Push 2Fruits+=('Watermelon') # Also Push 3Fruits=( ${Fruits[@]/Ap*/} ) # Remove by regex match 4unset Fruits[2] # Remove one item 5Fruits=("${Fruits[@]}") # Duplicate 6Fruits=("${Fruits[@]}" "${Veggies[@]}") # Concatenate 7lines=(`cat "logfile"`) # Read from file Iteration 1for i in "${arrayName[@]}"; do 2 echo $i 3done Dictionaries Defining 1declare -A sounds 1sounds[dog]="bark" 2sounds[cow]="moo" 3sounds[bird]="tweet" 4sounds[wolf]="howl" Declares sound as a Dictionary object (aka associative array). Working with dictionaries 1echo ${sounds[dog]} # Dog's sound 2echo ${sounds[@]} # All values 3echo ${!sounds[@]} # All keys 4echo ${#sounds[@]} # Number of elements 5unset sounds[dog] # Delete dog Iteration Operation Iterate over values 1for val in "${sounds[@]}"; do 2 echo $val 3done Iterate over keys 1for key in "${!sounds[@]}"; do 2 echo $key 3done Options set Options 1set -o noclobber # Avoid overlay files (echo "hi" > foo) 2set -o errexit # Used to exit upon error, avoiding cascading errors 3set -o pipefail # Unveils hidden failures 4set -o nounset # Exposes unset variables Glob options 1shopt -s nullglob # Non-matching globs are removed ('*.foo' => '') 2shopt -s failglob # Non-matching globs throw errors 3shopt -s nocaseglob # Case insensitive globs 4shopt -s dotglob # Wildcards match dotfiles ("*.sh" => ".foo.sh") 5shopt -s globstar # Allow ** for recursive matches ('lib/**/*.rb' => 'lib/a/b/c.rb') Set GLOBIGNORE as a colon-separated list of patterns to be removed from glob matches. History Commands Command Description history Show history shopt -s histverify Don't execute expanded result immediately Expansions Expression Description !$ Expand last parameter of most recent command !* Expand all parameters of most recent command !-n Expand nth most recent command !n Expand nth command in history !<command> Expand most recent invocation of command <command> Operation Info Code Description !! Execute last command again !!:s/<FROM>/<TO>/ Replace first occurrence of <FROM> to <TO> in most recent command !!:gs/<FROM>/<TO>/ Replace all occurrences of <FROM> to <TO> in most recent command !$:t Expand only basename from last parameter of most recent command !$:h Expand only directory from last parameter of most recent command !! and !$ can be replaced with any valid expansion. Slices Code Description !!:n Expand only nth token from most recent command (command is 0; first argument is 1) !^ Expand first argument from most recent command !$ Expand last token from most recent command !!:n-m Expand range of tokens from most recent command !!:n-$ Expand nth token to last from most recent command !! can be replaced with any valid expansion i.e. !cat, !-2, !42, etc. Miscellaneous Numeric calculations 1$((a + 200)) # Add 200 to $a 1$(($RANDOM%200)) # Random number 0..199 Subshells 1(cd somedir; echo "I'm now in $PWD") 2pwd # still in first directory Redirection 1python hello.py > output.txt # stdout to (file) 2python hello.py >> output.txt # stdout to (file), append 3python hello.py 2> error.log # stderr to (file) 4python hello.py 2>&1 # stderr to stdout 5python hello.py 2>/dev/null # stderr to (null) 6python hello.py &>/dev/null # stdout and stderr to (null) 1python hello.py < foo.txt # feed foo.txt to stdin for python Inspecting commands 1command -V cd 2#=> "cd is a function/alias/whatever" Trap errors 1trap 'echo Error at about $LINENO' ERR or 1traperr() { 2 echo "ERROR: ${BASH_SOURCE[1]} at about ${BASH_LINENO[0]}" 3} 4 5set -o errtrace 6trap traperr ERR Case/switch 1case "$1" in 2 start | up) 3 vagrant up 4 ;; 5 6 *) 7 echo "Usage: $0 {start|stop|ssh}" 8 ;; 9esac Source relative 1source "${0%/*}/../share/foo.sh" printf 1printf "Hello %s, I'm %s" Sven Olga 2#=> "Hello Sven, I'm Olga 3 4printf "1 + 1 = %d" 2 5#=> "1 + 1 = 2" 6 7printf "This is how you print a float: %f" 2 8#=> "This is how you print a float: 2.000000" Directory of script 1DIR="${0%/*}" Getting options 1while [[ "$1" =~ ^- && ! "$1" == "--" ]]; do case $1 in 2 -V | --version ) 3 echo $version 4 exit 5 ;; 6 -s | --string ) 7 shift; string=$1 8 ;; 9 -f | --flag ) 10 flag=1 11 ;; 12esac; shift; done 13if [[ "$1" == '--' ]]; then shift; fi Heredoc 1cat <<END 2hello world 3END Reading input 1echo -n "Proceed? [y/n]: " 2read ans 3echo $ans 1read -n 1 ans # Just one character Special variables Expression Description $? Exit status of last task $! PID of last background task $$ PID of shell $0 Filename of the shell script $_ Last argrument of the previous command See Special parameters. Go to previous directory 1pwd # /home/user/foo 2cd bar/ 3pwd # /home/user/foo/bar 4cd - 5pwd # /home/user/foo Check for command's result 1if ping -c 1 google.com; then 2 echo "It appears you have a working internet connection" 3fi Grep check 1if grep -q 'foo' ~/.bash_history; then 2 echo "You appear to have typed 'foo' in the past" 3fi Also see Bash-hackers wiki (bash-hackers.org) Shell vars (bash-hackers.org) Learn bash in y minutes (learnxinyminutes.com) Bash Guide (mywiki.wooledge.org) ShellCheck (shellcheck.net)