选项
-c 命令来自第一个非选项参数,如果命令字符串后面还有参数,第一个参数赋值给$0,后面的参数依次排序,例如执行bash -c 'echo $@' 1 2 3 4的输出为2 3 4
-i interactive,交互式
-l 或 --login 让bash的行为类似于登录shell
-r 受限的bash
-s 如果有 -s 选项,或者如果选项处理完以后,没有参数剩余,那么命令将从标准输入读取。 这个选项允许在启动一个交互 shell 时可以设置位置参数。
-v shell读取的时候打印输入行
-x 执行的时候打印命令及参数
-D 向标准输出打印一个以 $ 为前导的,以双引号引用的字符串列表。 这是在当前语言环境不是 C 或 POSIX 时,脚本中需要翻译的字符串。 这个选项隐含了 -n 选项;不会执行命令
[-+]O [shopt_option] shopt_option 是一个 shopt 内建命令可接受的选项 (参见下面的 shell 内建命令(SHELL BUILTIN COMMANDS) 章节)。 如果有 shopt_option,-O 将设置那个选项的取值; +O 取消它。 如果没有给出 shopt_option,shopt 将在标准输出上打印设为允许的选项的名称和值。 如果启动选项是 +O,输出将以一种可以重用为输入的格式显示。
-- – 标志选项的结束,禁止其余的选项处理。任何 – 之后的参数将作为文件名和参数对待。参数 - 与此等价
内建命令set中的单字符选项也可以使用
参数 没有指定 -c 或 -s 选项下,第一个参数将假定为一个包含 shell 命令的文件的名字。 如果 bash 是以这种方式启动的, $0 将设置为这个文件的名字,位置参数将设置为剩余的其他参数。 Bash 从这个文件中读取并执行命令,然后退出。 Bash 的退出状态是脚本中执行的最后一个命令的退出状态。 如果没有执行命令,退出状态是0。 尝试的步骤是先试图打开在当前目录中的这个文件,接下来, 如果没有找到,shell 将搜索脚本的 PATH 环境变量中的路径
builtins : : [arguments]
扩展参数,执行重定向外什么也不做,退出状态为0
. . filename [arguments]
在当前shell上下文中读取和执行的filename中的命令。退出状态是最后执行的命令的退出状态;如果未执行任何命令,则返回零。如果找不到文件名或无法读取文件名,则返回状态为非零。此内置命令等价于source
break break [n]
从for, while, until 或 select中退出。 如果提供了n,则退出第n个循环。n必须大于或等于1。返回状态为零,除非n不是大于或等于1。
continue continue [n]
继续循环的下一次迭代,其它同break
IFS IFS的默认值为空白字符(换行符、制表符或者空格)。
alias 1 2 3 4 5 6 7 8 9 10 11 12 13 $ alias $ alias -p $ alias ll='ls -l' $ alias ll alias ll='ls -l' $ unalias ll $ alias llbash: alias: ll: not found $ alias ll=$ alias llalias ll='' $ alias ls ='ls -l' $ \ls
arithmetic
(( expression ))
let "expression"
如果表达式的值非零,则返回状态为0;否则返回状态为1
1 2 3 4 5 6 7 i=0 ((i++)) echo $i # 1 ((i = i + 1)) echo $i # 2 let "i = i * 5" echo $i # 10
数组 普通数组 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 # !/bin/bash array_var=(test1 test2 test3 test4) # 这些值将会存储在以0为起始索引的连续位置上 echo ${array_var[0]} # test1 array_var[0]=ttt echo ${array_var[0]} # ttt i=3 echo ${array_var[$i]} # test4 array_var[4]=test5 echo ${array_var[*]} # ttt test2 test3 test4 test5 array_var[10]=test6 echo ${array_var[*]} # ttt test2 test3 test4 test5 test6 echo ${array_var[@]} # ttt test2 test3 test4 test5 test6 echo ${#array_var[*]} # 6 echo ${!array_var[*]} # 0 1 2 3 4 10 array_var[-1]=test7 echo ${array_var[*]} # ttt test2 test3 test4 test5 test7 echo ${!array_var[*]} # 0 1 2 3 4 10 array_var[-2]=test8 echo ${array_var[*]} # ttt test2 test3 test4 test5 test8 test7 echo ${!array_var[*]} # 0 1 2 3 4 9 10
关联数组 首先,需要使用声明语句将一个变量定义为关联数组
1 2 3 4 5 6 7 8 9 10 11 12 13 # !/bin/bash declare -A ass_array # 使用声明语句将一个变量定义为关联数组 ass_array=([index1]=val1 [index2]=val2) echo ${ass_array[index1]} # val1 ass_array[index3]=val3 echo ${ass_array[index3]} # val3 echo ${#ass_array[*]} # 3 echo ${ass_array[*]} # val1 val3 val2 echo ${!ass_array[*]} # index1 index3 index2
Job Control bg, fg, jobs, kill, wait, disown, suspend
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 $ ./main & [1] 32598 $ jobs [1]+ 运行中 ./main & $ ./main ^Z [2]+ 已停止 ./main $ jobs [1]- 运行中 ./main & [2]+ 已停止 ./main $ bg %2[2]+ ./main & $ jobs [1]- 运行中 ./main & [2]+ 运行中 ./main & $ fg %2./main ^C $ kill %1$ [1]+ 已终止 ./main
1 2 3 4 5 6 $ ./main & [1] 32679 $ disown %1$ jobs $ pgrep main 32679
1 2 3 4 5 6 7 8 9 10 11 12 13 14 $ kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX
内建命令 builtin
内建命令不需要使用子进程来执行,包括cd, exit, type, alias, ., echo, history等
case 1 2 3 case word in [ [(] pattern [| pattern]…) command-list ;;]… esac
1 2 3 4 5 6 7 8 9 10 11 12 read ans case $ans in y | Y | yes | YES) echo 'YES' ;; n | N | no | NO) echo 'NO' ;; *) echo '??' ;; esac
每个case子句以;;, ;& 或 ;;&结束
;; 在第一次模式匹配之后不尝试后续匹配
;& 在第一次模式匹配之后继续执行下一条子句
;;& 在第一次模式匹配之后继续匹配,并在匹配的子句处往下执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 read ans case $ans in 1) echo 1; ;& # 输入1,输出为1 2 2) echo 2; # 输入2,输出为2 ;; 3) echo 3; # 输入3,输出为3 ?? ;;& *) echo '??' ;; esac
类比C语言的switch, ;; 即 C语言中的break, ;&为不加break的分支,;;&则再进行一次匹配
退出状态 如果没有匹配项,退出状态为0,否则为执行命令的退出状态
echo - 显示字符串 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 $ type echo echo 是 shell 内建 $ echo "hello, world." hello, world. $ echo hello, worldhello, world $ echo $0 /bin/bash $ echo $?0 $ echo $$4728 $ echo $HOME /home/liph $ echo `date +%F`2020-07-13
选项
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 -n 不输出尾随的换行符 -E 禁用解释反斜杠的转义功能(默认) -e 启用解释反斜杠的转义功能 若 -e 可用,则以下序列即可识别: \\ 反斜线 \a 报警符(BEL) \b 退格符 \c 禁止尾随的换行符 \e escape 字符 \f 换页符 \n 另起一行 \r 回到行首 \t 水平制表符 \v 垂直制表符 \0NNN 字节数以八进制数 NNN (1至3位)表示 \xHH 字节数以十六进制数 HH (1至2位)表示
exec exec命令创建全新的文件描述符
1 2 3 exec 3<input.txt #使用文件描述符3打开并读取文件 exec 4>output.txt #打开文件进行写入 exec 5>>input.txt
Shell 扩展 Shell有7种扩展,扩展的顺序是大括号扩展;波浪号扩展;参数和变量扩展;算术扩展;命令替换;单词拆分;文件名扩展。如果系统支持,还有一种扩展:进程替换,它和波浪号、参数、变量、算术扩展以及命令替换是同时进行的。
大括号扩展 1 2 3 4 5 6 $ echo a{a,b,c}aa ab ac $ echo 0{1..9}01 02 03 04 05 06 07 08 09 $ echo 0{1..9..3}01 04 07
波浪号扩展 1 2 3 4 5 6 7 8 9 ~ /home/liph ~liph /home/liph ~root /root ~/tmp /home/liph/tmp ~+ $PWD ~- $OLDPWD ~N dirs +N ~+N dirs +N ~-N dirs -N
参数扩展 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 # ${parameter:−word} 如果参数没有设置或为空,替换为单词;否则为参数# ${parameter:=word} 如果参数没有设置或为空,把单词赋值给参数# ${parameter:?word} 如果参数没有设置或为空,把单词写到标准错误,退出shell# ${parameter:+word} 如果参数没有设置或为空,不进行任何替换;否则替换为单词# ${parameter:offset} 参数:偏移量# ${parameter:offset:length} 参数:偏移量:长度,如果长度是负数,则表示结尾的偏移量str='hello, world' echo ${#str} # 12, 长度 echo ${str:0:${#str}} # hello, world echo ${str:1} # ello, world echo ${str:1:-1} # ello, worl echo ${str:-1} # hello, world echo ${var} # echo ${var:-abc} # abc echo ${var} # echo ${var:=abc} # abc echo ${var} # abc echo ${var:=bcd} # abc # echo ${new:?bcd} echo ${var:?bcd} # abc echo ${var2:+bcd} echo ${var:+bcd} # bcd echo ${var} # abc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 # ${!prefix*} # ${!prefix@} 扩展为名称中含有前缀的变量,以IFS的第一个字符分隔。如果使用了@,并且在双引号内扩展,则每个变量都扩展成单独的单词var1=hello var2=world echo ${!var*} # var1 var2 # ${!name[@]} # ${!name[*]} 如果名称是个数组,扩展成数组下标或者key列表array=(a b c) echo ${!array[*]} # 0 1 2 array[100]=xyz echo ${!array[*]} # 0 1 2 100 # ${#parameter} 参数扩展后的字符数,如果是带下标*/@的数组名,则为数组中的元素个数echo ${#var1} # 5 echo ${#array[*]} # 4 echo ${#array} # 1 # ${parameter#word} # ${parameter##word} 单词被扩展成一个模式,如果模式匹配参数扩展后的开始部分,则替换的结果是该模式最短(var='a1a1a1' echo ${var#a*a} # 1a1 echo ${var##a*a} # 1 # ${parameter%word} # ${parameter%%word} 同上,从后匹配echo ${var%1*1} # a1a echo ${var%%1*1} # a # ${parameter/pattern/string} var=0a1a echo ${var/a/A} # 0A1a 替换第一个 echo ${var//a/A} # 0A1A 全替换 echo ${var/#a/A} # 0a1a 替换开头的第一个 echo ${var/%a/A} # 0a1A 替换结尾的第一个 echo ${var/a/} # 01a # ${parameter^pattern} # ${parameter^^pattern} # ${parameter,pattern} # ${parameter,,pattern} 大小写替换var=abCD echo ${var^*} # AbCD echo ${var^^*} # ABCD echo ${var,*} # abCD, 把a替换小写,无变化 echo ${var,,*} # abcd # ${parameter@operator} Q E P A avar=abc\ d echo ${var@Q} # 'abc d', 即quote echo ${var@E} # abc d, 即escape var='\u' echo ${var@P} # liph, 即prompt, 按PS1方式展开 echo ${var@A} # var='\u', 即assignment readonly var echo ${var@A} # declare -r var='\u' echo ${var@a} # r, 即attribute,获取属性
命令替换
算术扩展
进程替换 1 2 3 <(list) or >(list) '<' 或 '>' 与左边括号之间不能有空格,否则会被解释成重定向
History fc, history
fc fc [-e ename] [-lnr] [first] [last]
从历史列表中列出或者重新编辑并执行命令。 FIRST 和 LAST 变量可以是数字用于指定范围,或者 FIRST 可以是字符串,意味着以这个字符串打头的最近的一个命令
-e 编辑器, 如果不指定则为 ${FCEDIT:-${EDITOR:-vi}}
-l 列出行而不编辑
-n 列举时省略行号
-r 反转行的顺序(最新行在前)
fc -s [pat=rep] [command]
命令会在替换之后被重新执行
1 2 3 4 $ sduo apt update bash: sduo:未找到命令 $ fc -s sduo=sudosudo apt update
history history [n] 列出最后n行历史命令,每个被修改的条目加上 * 前缀
history -c 删除所有条目从而清空历史列表
1 2 3 $ history -c$ history 1 history
history -d offset 从指定位置删除历史列表。负偏移量将从历史条目末尾开始计数
history -d start-end 删除start 与 end 之间的历史列表
history [-anrw] [filename]
-a 将当前会话的历史行追加到历史文件中
-n 从历史文件中读取所有未被读取的行并且将它们附加到历史列表
-r 读取历史文件并将内容追加到历史列表中
-w 将当前历史写入到历史文件中
history -ps arg
-p 对每一个 ARG 参数展开历史并显示结果,而不存储到历史列表中
-s 以单条记录追加 ARG 到历史列表中
函数 函数定义
name () compound-command [ redirections ]
function name [()] compound-command [ redirections ]
复合命令(Compound Commands)包括循环,条件与组分组命令(Grouping Commands)
退出状态 函数定义的退出状态为零,除非出现语法错误或已存在同名的只读函数。在执行时,如果给定一个数值参数返回(return),这是函数的返回状态;否则,函数的返回状态是返回前执行的最后一个命令的退出状态 。
调用函数 1 2 fname; # 使用函数名执行函数 fname arg1 arg2; # 传递参数
1 2 3 4 5 6 7 function func() { echo $1; echo "$@"; return 0; } func hello world;
输出
其中
1 2 3 4 5 6 7 $0是脚本名称。 $1是第一个参数。 $2是第二个参数。 $n是第n个参数。 "$@"被扩展成"$1""$2""$3"等。 "$*"被扩展成"$1c$2c$3",其中c是IFS的第一个字符。 "$@"要比"$*"用得多。由于"$*"将所有的参数当作单个字符串,因此它很少被使用。
递归 1 2 3 4 5 6 7 function func() { echo hello; sleep 1; func; } func;
bash也支持递归函数,自身调用自己(或循环调用)
1 :(){ :|:& };: # fork 炸弹,":" 可作为函数名
变量 使用local定义变量将仅对函数及其调用的命令可见
1 2 3 4 5 6 7 8 9 10 11 12 13 func1() { local var='func1 local' func2 } func2() { echo "In func2, var = $var" } var=global func1 # => In func2, var = func1 local
Grouping Commands ( list )
在圆括号之间放置一列命令将创建一个子shell环境,列表中的每个命令将在该子shell中执行。由于该列表是在子shell中执行的,所以在子shell完成后,变量分配将不再有效。
{ list; }
在花括号之间放置一个命令列表将导致该列表在当前shell上下文中执行。不创建子shell。必须使用列表后面的分号(或换行符)。
此外,大括号是保留字,因此必须用空格或其他shell元字符将它们与列表分隔开。括号是操作符,即使它们与列表之间没有空格,shell也会将它们识别为单独的标记。这两个构造的退出状态都是list的退出状态。
比较与测试 if 用法
1 2 3 4 if condition; then commands; fi
以及
1 2 3 4 5 6 7 8 9 if condition; then commands; elif condition; then commands; else commands; fi
算术比较 比较条件通常被放置在封闭的中括号内。一定要注意在[ 或 ]与操作数之间有一个空格。如果忘记了这个空格,脚本就会报错。
对变量或值进行算术条件测试:
[ $var -eq 0 ] 当$var等于0时,返回真[ $var -ne 0 ] 当$var不为0时,返回真
其他重要的操作符如下。
1 2 3 4 -gt:大于。 -lt:小于。 -ge:大于或等于。 -le:小于或等于。
-a是逻辑与操作符,-o是逻辑或操作符。可以按照下面的方法结合多个条件进行测试:[ $var1 -ne 0 -a $var2 -gt 2 ] 以及 [ $var1 -ne 0 -o $var2 -gt 2 ]
文件系统相关测试 1 2 3 4 5 6 7 8 9 [ -f $file_var ]:如果给定的变量包含正常的文件路径或文件名,则返回真。 [ -x $var ]:如果给定的变量包含的文件可执行,则返回真。 [ -d $var ]:如果给定的变量包含的是目录,则返回真。 [ -e $var ]:如果给定的变量包含的文件存在,则返回真。 [ -c $var ]:如果给定的变量包含的是一个字符设备文件的路径,则返回真。 [ -b $var ]:如果给定的变量包含的是一个块设备文件的路径,则返回真。 [ -w $var ]:如果给定的变量包含的文件可写,则返回真。 [ -r $var ]:如果给定的变量包含的文件可读,则返回真。 [ -L $var ]:如果给定的变量包含的是一个符号链接,则返回真。
字符串比较 进行字符串比较时,最好用双中括号,因为有时候采用单个中括号会产生错误。双中括号是Bash的一个扩展特性。如果出于性能考虑,使用ash或dash来运行脚本,那么将无法使用该特性。
1 2 3 4 5 6 7 [[ $str1 = $str2 ]]:当str1等于str2时,返回真。也就是说,str1和str2包含的文本是一模一样的。 [[ $str1 == $str2 ]]:这是检查字符串是否相同的另一种写法。测试两个字符串是否不同。 [[ $str1 != $str2 ]]:如果str1和str2不相同,则返回真。 [[ $str1 > $str2 ]]:如果str1的字母序比str2大,则返回真。 [[ $str1 < $str2 ]]:如果str1的字母序比str2小,则返回真。 [[ -z $str1 ]]:如果str1为空串,则返回真。 [[ -n $str1 ]]:如果str1不为空串,则返回真。
test test命令可以用来测试条件。用test可以避免使用过多的括号,增强代码的可读性。[]中的测试条件同样可以用于test命令。
if [ $var -eq 0 ]; then echo "True"; fi 可以写if test $var -eq 0 ; then echo "True"; fi
test是一个外部程序,需要衍生出对应的进程,而 [ 是Bash的一个内部函数,因此后者的执行效率更高。test兼容于Bourne shell、ash、dash等。
Lists of Commands 1 2 3 4 cmd1 && cmd2 # 当且仅当cmd1退出状态为0才执行cmd2 cmd1 || cmd2 # 当且仅当cmd1退出状态不为0才执行cmd2 cmd1 ; cmd2 # 按顺序执行cmd1,cmd2 cmd & # 后台异步执行cmd
优先级 && 和 || 相同,优于优先级相同的 ; 和 &
循环 for for name [ [in [lists …] ] ; ] do commands; donefor (( expr1 ; expr2 ; expr3 )) ; do commands ; done
面向列表的for循环 1 2 3 4 for var in list; do commands; done
list可以是一个字符串,也可以是一个值序列
值序列 {A..Z}, {0..9} {a..z}
1 2 3 4 $ echo {A..Z}A B C D E F G H I J K L M N O P Q R S T U V W X Y Z $ echo {a..z} {0..9}a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9
如果不指定in lists,默认为in $@
迭代指定范围的数字 1 2 3 4 for((i=0; i<10; i++)) { commands; }
while while test-commands; do consequent-commands; done
1 2 3 4 while true; do commands; done
用true作为循环条件能够产生无限循环
until until test-commands; do consequent-commands; done
until会一直循环,直到给定的条件为真。
1 2 3 4 5 6 x=0; until [ $x -eq 9 ]; do let x++; echo $x; done
无限循环 while true; do cmd; done 等价于 until false; do cmd; done
三种循环都可以使用break,continue来控制
pipeline 1 2 cmd1 | cmd2 # cmd1的标准输出成为cmd2的标准输入 cmd1 |& cmd2 # cmd1的标准输出、标准错误成为cmd2的标准输入,类似于cmd1 2>&1 | cmd2
未开启pipefail选项下,管道的退出状态是最后一条命令的退出状态
pwd - print work directory 输出当前工作目录的完整名称
1 2 3 4 5 6 $ type -a pwd pwd 是 shell 内建 pwd 是 /usr/bin/pwd pwd 是 /bin/pwd $ pwd /home/liph
return return [n]
用来退出函数并指定退出状态,如果没用指定n,退出状态为函数执行的最后一条命令的退出状态
1 2 3 4 5 6 7 $ return bash: return: 只能从函数或者源脚本返回(`return') $ cat test.shreturn $ bash test.sh test.sh: 第 1 行:return: 只能从函数或者源脚本返回(`return') $ source test.sh
在终端中输入return,得到提示return只能在函数或由 . 和source命令执行的脚本中使用
select select name [in words …]; do commands; done
如果省略in words,则会指定in $@
创建菜单供用户选择
1 2 3 4 5 6 7 echo "select your linux distribution" linux="Debian Centos Ubuntu Arch" select os in $linux: do echo "your select is ${REPLY}, $os is the best!" break; done
1 2 3 4 5 6 7 8 $ bash select.sh select your linux distribution 1) Debian 2) Centos 3) Ubuntu 4) Arch: # ? 1 your select is 1, Debian is the best!
set 1 2 set [--abefhkmnptuvxBCEHPT] [-o option-name] [argument …] set [+abefhkmnptuvxBCEHPT] [+o option-name] [argument …]
如果不指定参数,set会打印出所有变量与函数
选项
1 2 3 4 5 6 7 8 -e 如果命令退出状态非0,立即退出shell -x 执行命令前先打印(先扩展变量`PS4`后打印命令) +x 禁止调试 -v 当命令进行读取时显示输入 +v 禁止打印输入 -u 视未设置的变量和参数(特殊参数@或*除外)为错误,在标准错误写入错误信息,并退出非交互运行的shell -o pipefail 只要管道中有任何一个命令返回非0,则整个管道操作被视为失败
使用选项-x,启用shell脚本的跟踪调试功能:$ bash -x script.sh
使用set -x和set +x对脚本进行部分调试
1 2 3 4 5 6 7 # !/bin/bash for i in {1..6}; do set -x echo $i set +x done
把shebang从#!/bin/bash改成#!/bin/bash -xv,这样一来,不用任何其他选项就可以启用调试功能了
如果使用了-x -v或set -x -v,调试输出会被发送到stderr
shell styleguide 参考
https://google.github.io/styleguide/shellguide.html
time time [-p] command [arguments...]
-p POSIX格式输出
time的输出
real 时钟时间
user 用户态CPU时间
sys 内核态CPU时间
type 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 $ type -t type builtin $ type ls ls 是“ls --color=auto”的别名 $ type -a ls ls 是“ls --color=auto”的别名 ls 是 /usr/bin/ls ls 是 /bin/ls $ type mkcdmkcd 是函数 mkcd () { dir=$1; mkdir -p "${dir}"; cd "${dir}" } $ type -f mkcd bash: type: mkcd:未找到 $ type -P ls /usr/bin/ls $ type -t ls alias $ type -p ls
变量
变量名由一系列字母、数字和下划线组成,其中不包含空白字符,变量包含一个值与0或多个属性,属性由declare来声明。
常用的惯例是在脚本中使用大写字母命名环境变量,使用驼峰命名法或小写字母命名其他变量。
赋值操作:name=[value],其中,空字符串是一个有效值
如果value不包含任何空白字符(例如空格),那么就不需要将其放入引号中,否则必须使用单引号或双引号
var = value不同于var=value。两边没有空格的等号是赋值操作符,加上空格的等号表示的是等量关系测试。
在变量名之前加上美元符号($)就可以访问变量的内容
echo $var 也可以这样写:echo ${var}
使用单引号时,变量不会被扩展,仍依照原样显示。这意味着echo '$var'会显示$var。
但如果变量var已经定义过,那么echo "$var"会显示出该变量的值;如果没有定义过,则什么都不显示。
可以用下面的方法获得变量值的长度:`length=$