bash_shell脚本
- 更换系统默认 shell
shell 类型
- /bin/sh (已经被 /bin/bash 所取代)
- /bin/bash (就是 Linux 默认的 shell)
- /bin/tcsh (整合 C Shell ,提供更多的功能)
- /bin/csh (已经被 /bin/tcsh 所取代)
- zsh
Bash shell 功能
命令编修能力 (history)~/.bash_history
命令与文件补全功能(tab 键)
命令别名设置功能(alias)
程序化脚本(shell scripts)
万用字符(Wildcard)*
特殊符号
符号 | 内容 |
---|---|
# | 注解符号:这个最常被使用在 script 当中,视为说明!在后的数据均不执行 |
\ | 跳脱符号:将“特殊字符或万用字符”还原成一般字符 |
| | 管线 (pipe):分隔两个管线命令的界定(后两节介绍); |
; | 连续指令下达分隔符号:连续性命令的界定 (注意!与管线命令并不相同) |
~ | 使用者的主文件夹 |
\$ | 取用变量前置字符:亦即是变量之前需要加的变量取代值 |
& | 工作控制 (job control):将指令变成背景下工作 |
! | 逻辑运算意义上的“非” not 的意思! |
/ | 目录符号:路径分隔的符号 |
>, >> | 数据流重导向:输出导向,分别是“取代”与“累加” |
<, << | 数据流重导向:输入导向 (这两个留待下节介绍) |
' ' | 单引号,不具有变量置换的功能 (\$ 变为纯文本) |
" " | 具有变量置换的功能! (\$ 可保留相关功能) |
` ` | 两个“ ` ”中间为可以先执行的指令,亦可使用 \$( ) |
( ) | 在中间为子 shell 的起始与结束 |
{ } | 在中间为命令区块的组合! |
变量
变量的取用 echo
echo $varible
echo ${varible}
变量设定规则
=
设置变量,且前后不能有空格双引号内的特殊字符如 \$ 等,可以保有原本的特性,如下所示:
var="lang is $LANG"
则echo $var
可得lang is zh_TW.UTF-8
单引号内的特殊字符则仅为一般字符 (纯文本),如下所示:
var='lang is $LANG'
则echo $var
可得lang is $LANG
使用
\
转义特殊字符使用``
export varible
使变量变成环境变量子程序
在当前这个 shell 的情况下,去启用另一个新的 shell ,新的那个 shell 就是子程序
在一般的状态下,父程序的变量无法在子程序内使用。但通过 export 将变量变成环境变量后,就能够在子程序下面是使用了
unset varible
取消变量单引号与双引号必须成对,否则会报错
env
列出当前 shell 环境下所有环境变量set
列出自定义变量和环境变量$
和?
变量$
是本 shell 的线程代号(pid)?
是上一个执行命令的回传值,如果上个指令成功执行,则会回传一个 0;有错误否则非 0export
将自定义变量转成环境变量子程序仅会继承父程序的环境变量, 子程序不会继承父程序的自订变量
变量键盘读取与宣告
read
读取来自键盘输入的变量read [-pt] varible选项与参数:-p :后面可以接提示字符!-t :后面可以接等待的“秒数!”这个比较有趣~不会一直等待使用者啦!declare / typeset
定义变量的类型declare [-aixr] variable选项与参数:-a :将后面名为 variable 的变量定义成为阵列 (array) 类型-i :将后面名为 variable 的变量定义成为整数数字 (integer) 类型-x :用法与 export 一样,就是将后面的 variable 变成环境变量;-r :将变量设置成为 readonly 类型,该变量不可被更改内容,也不能 unsetsum=100+300+50echo ${sum} => '100+300+50'declare -i sum=100+300+50echo ${sum} => 450- 变量类型默认为“字串”,所以若不指定变量类型,则 1+2 为一个“字串”而不是“计算式”。
- bash 环境中的数值运算,默认最多仅能到达整数形态,所以 1/3 结果是 0;
数组
Shell scripts
- 为啥学习
- 自动化管理
- 追踪与管理系统
- 简单入侵侦测
- 连续指令单一化
- 简易的数据处理
- 跨平台支持与学习历程较短
- 注意事项
- 指令的执行是从上而下、从左而右的分析与执行;
- 指令、选项与参数间的多个空白都会被忽略掉;
- 空白行也将被忽略掉,并且 [tab] 按键所推开的空白同样视为空白键;
- 如果读取到一个 Enter 符号 (CR) ,就尝试开始执行该行 (或该串) 命令;
- 至于如果一行的内容太多,则可以使用“ [Enter] ”来延伸至下一行;
- “ # ”可做为注解!任何加在 # 后面的数据将全部被视为注解文字而被忽略!
read
指令实现对谈式脚本$(())
进行数值运算。仅支持整数- script 执行的方式差异
- 直接执行:在子程序中执行(变量不会传到父程序) * 当使用前一小节提到的直接指令下达 (不论是绝对路径/相对路径还是 \${PATH} 内),或者是利用 bash (或 sh) 来下达脚本时, 该 script 都会使用一个新的 bash 环境来执行脚本内的指令
- 利用 source 执行:在父程序中执行
判断式
test
测试测试的标志 代表意义 1. 关于某个文件名的“文件类型”判断,如 test -e filename 表示存在否 -e 该“文件名”是否存在?(常用) -f 该“文件名”是否存在且为文件(file)?(常用) -d 该“文件名”是否存在且为目录(directory)?(常用) -b 该“文件名”是否存在且为一个 block device 设备? -c 该“文件名”是否存在且为一个 character device 设备? -S 该“文件名”是否存在且为一个 Socket 文件? -p 该“文件名”是否存在且为一个 FIFO (pipe) 文件? -L 该“文件名”是否存在且为一个链接文件? 2. 关于文件的权限侦测,如 test -r filename 表示可读否 (但 root 权限常有例外) -r 侦测该文件名是否存在且具有“可读”的权限? -w 侦测该文件名是否存在且具有“可写”的权限? -x 侦测该文件名是否存在且具有“可执行”的权限? -u 侦测该文件名是否存在且具有“SUID”的属性? -g 侦测该文件名是否存在且具有“SGID”的属性? -k 侦测该文件名是否存在且具有“Sticky bit”的属性? -s 侦测该文件名是否存在且为“非空白文件”? 3. 两个文件之间的比较,如: test file1 -nt file2 -nt (newer than)判断 file1 是否比 file2 新 -ot (older than)判断 file1 是否比 file2 旧 -ef 判断 file1 与 file2 是否为同一文件,可用在判断 hard link 的判定上。 主要意义在判定,两个文件是否均指向同一个 inode 哩! 4. 关于两个整数之间的判定,例如 test n1 -eq n2 -eq 两数值相等 (equal) -ne 两数值不等 (not equal) -gt n1 大于 n2 (greater than) -lt n1 小于 n2 (less than) -ge n1 大于等于 n2 (greater than or equal) -le n1 小于等于 n2 (less than or equal) 5. 判定字串的数据 test -z string 判定字串是否为 0 ?若 string 为空字串,则为 true test -n string 判定字串是否非为 0 ?若 string 为空字串,则为 false。 -n 亦可省略 test str1 == str2 判定 str1 是否等于 str2 ,若相等,则回传 true test str1 != str2 判定 str1 是否不等于 str2 ,若相等,则回传 false 6. 多重条件判定,例如: test -r filename -a -x filename -a (and)两状况同时成立!例如 test -r file -a -x file,则 file 同时具有 r 与 x 权限时,才回传 true。 -o (or)两状况任何一个成立!例如 test -r file -o -x file,则 file 具有 r 或 x 权限时,就可回传 true。 ! 反相状态,如 test ! -x file ,当 file 不具有 x 时,回传 true 判断符号
[]
(常用在 if then 条件语句中)在中括号 [] 内的每个元件都需要有空白键来分隔;
在中括号内的变量,最好都以双引号括号起来;
在中括号内的常数,最好都以单或双引号括号起来。
可以使用上面 test 中的参数比对
- # □代表空格[ "$HOME" == "$MAIL" ][□"$HOME"□==□"$MAIL"□]↑ ↑ ↑ ↑
shell script 的默认变数(内建变量)(\$0,\$1)
/path/to/scriptname opt1 opt2 opt3 opt4$0 $1 $2 $3 $4执行的脚本文件名为 \$0 这个变量,第一个接的参数就是 \$1
\$# :代表后接的参数“个数”,以上表为例这里显示为“ 4 ”;
\$@ :代表
"$1" "$2" "$3" "$4"
之意,每个变量是独立的(用双引号括起来);\$* :代表
"$1<u>c</u>$2<u>c</u>$3<u>c</u>$4"
,其中<u>c</u>
为分隔字符,默认为空白键, 所以本例中代表"$1 $2 $3 $4"
之意。shift
可以造成参数变量号偏移
条件判断式
if then
单层判断
if [ 条件判断式 ]; thenxxxx # 当条件判断式成立时,可以进行的指令工作内容;fi # 将 if 反过来写,就成为 fi 啦!结束 if 之意!多层判断
`if else
# 一个条件判断,分成功进行与失败进行 (else)if [ 条件判断式 ]; thenxxx #当条件判断式成立时,可以进行的指令工作内容;elsexxx #当条件判断式不成立时,可以进行的指令工作内容;fiif ... elif ... elif ... else
# 多个条件判断 (if ... elif ... elif ... else) 分多种不同情况执行if [ 条件判断式一 ]; thenxxx #当条件判断式一成立时,可以进行的指令工作内容;elif [ 条件判断式二 ]; thenxxx #当条件判断式二成立时,可以进行的指令工作内容;elsexxx #当条件判断式一与二均不成立时,可以进行的指令工作内容;fi
case...esac
判断case $变量名称 in #关键字为 case ,还有变量前有钱字号"第一个变量内容") #每个变量内容建议用双引号括起来,关键字则为小括号 )程序段;; #每个类别结尾使用两个连续的分号来处理!"第二个变量内容")程序段;;*) #最后一个变量内容都会用 * 来代表所有其他值#不包含第一个变量内容与第二个变量内容的其他程序执行段exit 1;;esac #最终的 case 结尾!“反过来写”思考一下!利用函数功能
function fname() {程序段}function 也是拥有内置变量
函数名称代表示 \$0 ,而后续接的变量也是以
$1, $2
循环
不定循环
while do done
while [ condition ] #中括号内的状态就是判断式do #do 是循环的开始!#程序段落done #done 是循环的结束until do done 与 while 相反
#当 condition 条件成立时,就终止循环, 否则就持续进行循环的程序段。until [ condition ]do程序段落done
固定循环
for var in con1 con2 con3 ...do程序段done#第一次循环时, $var 的内容为 con1 ;#第二次循环时, $var 的内容为 con2 ;#第三次循环时, $var 的内容为 con3 ;for (( 初始值; 限制值; 执行步阶 ))do程序段doneTips 1 到 100,除了使用 \$(seq 1 100) 之外,你也可以直接使用 bash 的内置机制来处理喔!可以使用 {1..100} 来取代 \$(seq 1 100) ! 那个大括号内的前面/后面用两个字符,中间以两个小数点来代表连续出现的意思!例如要持续输出 a, b, c...g 的话, 就可以使用“ echo {a..g} ”这样的表示方式!seq 是 sequence 是连续的缩写
shell scripts 的调试
sh [-nvx] scripts.sh选项与参数:-n :不要执行 script,仅查询语法的问题;-v :再执行 sccript 前,先将 scripts 的内容输出到屏幕上;-x :将使用到的 script 内容显示到屏幕上,这是很有用的参数!