Basic usage of Bash.

source

It executes the content of the file in the current shell.

synonym: . (period).

$-

echo $-
himBH
  • h: hashall:
  • i: interactive
  • m: monitor mode: CTRL+Z, fg
  • H: history expand: ~/.bash_history, !!
  • B: brace expansion: cp file{,.bak}

if [ "${-#*i}" != "$-" ] checking if your shell is interactive or not

$

  • $*: equivalent to $1c$2c...
  • $@: equivalent to $1 $2
  • $#: number of position parameters in decimal
  • $?: exit status of the most recently executed foreground pipeline
  • $-: the current option flags as specified upon invocation
  • $$: the process ID of the shell
  • $!: the process ID of the job most recently placed into background
  • $0: the name of the shell or shell script
  • $_: the absolution path name used to invoke the shell

A double dash (--) is used in bash built-in commands and many other commands to signify the end of command options, after which only positional parameters are accepted.

Example use: lets say you want to grep a file for the string -v - normally -v will be considered the option to reverse the matching meaning (only show lines that do not match), but with -- you can grep for string -v like this:

grep -- -v file

[ ]

[ ] vs [[ ]] are test operators

  • You no longer have to quote variables like mad because [[ handles empty strings and strings with whitespace more intuitively.
  • It lets you use && and || operators for boolean tests and < and > for string comparisons.
  • It has a wonderful =~ operator for doing regular expression matches.
  • You get pattern matching aka globbing for free.
if [ -f "$FILE" ]
if [[ -f $FILE ]]

if [ "$ANSWER" = y -o "$ANSWER" = yes ]
if [[ $ANSWER =~ ^y(es)?$ ]]

if [[ $ANSWER = y* ]]
-z字串 字串长度伪则为真。
-n字串 字串长度不伪则为真。
-e文件名 如果文件存在则为真。
-r文件名 如果文件存在且可读则为真。
-w文件名 如果文件存在且可写则为真。
-x文件名 如果文件存在且可执行则为真。
-s文件名 如果文件存在且至少有一个字符则为真。
-d文件名 如果文件存在且为目录则为真。
-f文件名 如果文件存在且为普通文件则为真。
-c文件名 如果文件存在且为字符型特殊文件则为真。
-b文件名 如果文件存在且为块特殊文件则为真

()

$() is command substitution

$ echo "my hostname is: $(hostname)"
my uptime is: MYPC

$(( )) is arithmetic expansion

$ echo "$(( 5 + 5 ))"
10

${ } This is used to refer to variables and avoid confusion over their name.

$ v="hello"
$ echo "$vbye"

$ echo "${v}bye"
hellobye

Also, it is used to reference array elements:

$ declare -A my_arr
$ my_arr[a]="hello"
$ echo "${my_arr[a]}"
hello

( ) and { } are also used as grouping commands

( ) runs in a subshell:

$ v=5
$ ( v=2; echo "$v" )
2
$ echo "$v"
5

Whereas { list, } does not:

$ v=5
$ { v=2; echo "$v"; }
2
$ echo "$v"
2

{ }

  • ${value:-word}: 当变量未定义或者值为空时,返回值为word的内容,否则返回变量的值.
  • ${value:=word}: 与前者类似,只是若变量未定义或者值为空时,在返回word的值的同时将word赋值给value
  • ${value:?message}: 若变量以赋值的话,正常替换.否则将消息message送到标准错误输出(若此替换出现在Shell程序中,那么该程序将终止运行)
  • ${value:+word}: 若变量以赋值的话,其值才用word替换,否则不进行任何替换
  • ${value:offset}, ${value:offset:length}: 从变量中提取子串,这里offset和length可以是算术表达式.
  • ${#value}: 变量的字符个数
  • ${value#pattern}, ${value##pattern}: 去掉value中与pattern相匹配的部分,条件是value的开头与pattern相匹配 #与##的区别在于一个是最短匹配模式,一个是最长匹配模式.
  • ${value%pattern}, ${value%%pattern}: 于(7)类似,只是是从value的尾部于pattern相匹配,%与%%的区别与#与##一样
  • ${value/pattern/string}, ${value//pattern/string}: 进行变量内容的替换,把与pattern匹配的部分替换为string的内容,/与//的区别与上同
INFORMIX_HOME="${INFORMIX_HOME%/}" # Strip the trailing / (if exists)

注意: 上述条件变量替换中,除(2)外,其余均不影响变量本身的值

set

set -euxo pipefail
  • -x: print commands and their arguments as they are executed
  • -e: equivalent to cmd1 && cmd2 && cmd3
  • -u: The shell prints a message to stderr when it tries to expand a variable that is not set. Also it immediately exits.
  • -o option-name: set the variable corresponding to option-name.
  • +o option-name: using + rather than - will cause the option to be turned off.
  • -o pipefail: Pipelines fail on the first command which fails instead of dying later on down the pipeline. This is especially good when cmd3 is a command that always succeeds (like echo)
  • -f: disable filename expansion (globbing) upon seeing *, ?, etc.

bash

here

-s  stdin   Read commands from stdin

BASH_SOURCE

#!/bin/sh
echo "${BASH_SOURCE[0]}"
echo "${BASH_SOURCE}"
echo "$( dirname "${BASH_SOURCE[0]}" )"
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
echo $DIR
./abc/test.sh
./abc/test.sh
./abc/
/home/abc

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 得到shell脚本文件所在完整路径(绝对路径)及文件名(无论source,sh,.三种调用方式),且不改变shell的当前目录。