阅读 119

shell脚本

shell是一个用C编写的成语,是用户使用Linux的桥梁。它既是一种命令语言,又是一种程序设计语言。

bash与shell脚本

shell脚本的解析器

  • Bash是一种运行shell脚本的解释器,是Linux默认使用的shell解释器。其它常见的shell解释器还有C Shell(csh)z shell(zsh)等。
  • shell脚本一般以.sh作为扩展名(仅作为辨识,不影响运行),且首行用以下语句指定shell解释器
#! /bin/bash
  • 对于指定了shell解释器的脚本,可以在命令行中给与可执行权限后直接运行。
sudo chmod +x script.sh
./script.sh
  • 而未指定shell解释器的脚本,可以用以下命令在运行时指定。此时文件中指定shell解释器的首行失效。(实际上是运行解释器,将脚本文件作为参数)
/bin/bash script.sh

shell脚本的特点

  • 不同语句可以用换行符,也可以用分号分隔写在一行

  • 当一行语句可以用(){}括起来时,有不同的效果

    • ()会开启一个子 Shell 执行;{}在 当前 Shell 中执行
    • {}中第一条命令与左括号之间必须有一个空格,且最后一条命令一定要用分号;()不必
    • (){}括号里面的某条命令的重定向只影响该命令,但括号外的重定向则会影响到括号里的所有命令
  • 前一条语句执行不成功不影响后面语句的执行

shell中的变量

  • 与大多数的语言一样,shell变量名的首个字符必须为字母;不能有除下划线以外的标点符号;不能使用bash里的关键字(可用help命令查看保留关键字)
  • Shell中的变量在定义时,变量名与等号=之间不能有空格(避免歧义,shell中常用空格做参数间的分隔符)。
  • 使用时,变量前必需加$,也可以用花括号将变量名括起来确定边界,例如:
#! /bin/bash
name="yexiaowo"
echo "your name is $name."
echo "your name is ${name}."

shell位置参数及特殊变量

$+数字0-9可以直接调用位置参数,规则如下:

变量 含义
$0 脚本本身(文件名)
$1 第一个位置参数
$n 第n个位置参数

例如脚本文件script.sh

#! /bin/bash
echo "your name is $1"

终端输入:/bin/bash script.sh yexiaowo
终端输出:your name is yexiaowo

还有其他特殊变量:

变量 含义
$# 参数个数
$* 所有参数(以双引号括起来时,所有参数为一整体)
$@ 所有参数
$? 上个命令的推出状态或函数返回值
$$ 当前shell进程的ID

shell字符串

在shell,无论是否有引号,定义的每个变量都被认为是字符串。

shell的字符串可以用单引号,也可以用双引号,也可以不用引号。但各有所区别:

  • 单引号为原样输出,不可转义和使用变量。(类似python的三对引号)
  • 双引号里可以有变量和转义字符
  • 不加引号与双引号类似,但不会将以空格等特殊字符分隔的字符串看作一个整体,仅可用于没有分隔符的字符串(不建议使用)

shell字符串拼接(变量替换)、子串和字符替换

与其他变成语言不同的是,shell中的变量可以直接插入任意位置进行字符串拼接(变量替换),例如:

a="yexiaowo"
b="my name is ${a}"
echo $b

以下的字符串分割命令常用于文件路径处理。

例如先定义一个变量为路径:file="~/dir1/dir2/dir3/a.file.sh",则有:

命令 作用 结果
${file#*/} 去掉第一个/及左侧的字符串 dir1/dir2/dir3/a.file.sh
${file##*/} 去掉最后一个/及左侧的字符串 a.file.sh
${file%/*} 去掉最后一个/及右侧的字符串 ~/dir1/dir2/dir3
${file%%/*} 去掉第一个/及右侧的字符串 ~

记忆方法为:键盘上#号在$左边,所以为去左,*号在匹配目标字符串左边,一个#为最小匹配(去掉的最少),两个##为最大匹配,%同理。

还有子串和字符替换

命令 作用 结果
${file:0:5} 提取第零个字符后的连续5个字符(前5个字符) ~/dir
${file/i/o} 将第一个字符i替换为o(后面一个o及/可以为空) ~/dor1/dir2/dir3/a.file.sh
${file//i/o} 将所有字符i替换为o(后面一个o及/可以为空) ~/dor1/dor2/dor3/a.fole.sh
${#file} 字符串长度 25

以及针对变量的不同状态赋值

命令 作用 备注
${file-a.file.sh} 假如 $file 没有设定,则使用 a.file.sh 作传回值 空值及非空值时不作处理
${file:-a.file.sh} 假如 $file 没有设定或为空值,则使用 a.file.sh 作传回值 非空值时不作处理
${file+a.file.sh} 假如 $file 设为空值或非空值,均使用 a.file.sht 作传回值 没设定时不作处理
${file:+a.file.sh} 若 $file 为非空值,则使用 a.file.sh 作传回值 没设定及空值时不作处理
${file=a.file.sh} 若 $file 没设定,则使用 a.file.sh 作传回值,同时将 $file 赋值为 a.file.sh 空值及非空值时不作处理
${file:=a.file.sh} 若 $file 没设定或为空值,则使用 a.file.sh 作传回值,同时将 $file 赋值为 a.file.sh 非空值时不作处理
${file?a.file.sh} 若 $file 没设定,则将 a.file.sh 输出至 STDERR 空值及非空值时不作处理
${file:?a.file.sh} 若 $file 没设定或为空值,则将 a.file.sh 输出至 STDERR 非空值时不作处理

记忆方法为:+-号意为是否有;带冒号:意为包含为空值情况;等号=意为同时赋值变量;问号?意为断言是在

shell 数组

shell中的数组用小括号定义,空格分隔。例如:array=(val1 val2 val3)

与shell数组有关的命令有:

命令 含义 结果
${array[*]} 全部元素 val1 val2 val3
${array[@]} 全部元素 val1 val2 val3
${array[0]} 索引为0的元素 val1
${#array[*]} 元素个数 3
${#array[@]} 元素个数 3
${#array[0]} 索引为0的元素的长度 4
A[0]=xy 将索引为0的元素赋值为xy

注:$array等价于${array[0]}

shell中的命令替换

在bash中,可以使用$()和` `作命令替换,来重组一行命令。即先完成引号里的命令行,然后将其结果替换出来,再重组成新的命令行。

例如:echo today is $(date "+%Y-%m-%d")

输出为:today is 2014-07-01

各自优点:

  • $()不易与引号混淆,且更直观,且在多层次的复合替换中,不须要额外的跳脱处理(反斜线,反引号需要)
  • ` `的兼容性更好,所以类linux系统均支持

例如:

cmd3 $(cmd2 $(cmd1))
cmd3 `cmd2 \`cmd1\``

shell中的运算

shell不支持浮点运算(浮点数只能作为字符串)。

运算使用$(())或者$[]进行(此时括号中的$符号可以省略)。

例如:

a=1;b=2;c=3
echo $[a+b*c]
echo $((a<<1))

shell脚本支持几乎所有的数学运算符、关系运算符、逻辑运算符和位操作符(与C++中用法一致)。

$(())$[]还能计算进制转换,如输出N进制数xx的十进制数可写为(xx也可以是变量):echo$[N#xx]

shell中的条件语句

条件测试

测试表达式是否成立,若成立返回0,否则返回其他数值。

格式一:test 表达式

格式二:[ 表达式 ]注:方括号与表达式之间必须用空格隔开

  • 文件测试:[ 操作符 文件或目录 ]
常用操作符 说明 示例
-e filename 如果filename存在,则为真 [ -e /var/log/syslog ]
-d filename 如果filename目录存在,则为真 [ -d /tmp/mydir ]
-f filename 如果filename文件存在,则为真 [ -f /usr/bin/grep ]
-L filename 如果filename符号链接存在,则为真 [ -L /usr/bin/grep ]
-r filename 如果filename可读,则为真 [ -r /var/log/syslog ]
-w filename 如果filename可写,则为真 [ -w /var/mytmp.txt ]
-x filename 如果filename可执行,则为真 [ -L /usr/bin/grep ]
filename1 -nt filename2 如果filename1比filename2新,则为真 [ /tmp/install/etc/services -nt /etc/services ]
filename1 -ot filename2 如果filename1比filename2旧,则为真 [ /tmp/install/etc/services -nt /etc/services ]
  • 整数值比较:[ 整数1 操作符 整数2 ]
常用操作符 说明 示例
-eq 等于(equal) [ $a -eq 1 ]
-ne 不等于(not equal) [ $a -ne 1 ]
-gt 大于(greater than) [ $a -gt 1 ]
-lt 小于(lesser than) [ $a -lt 1 ]
-ge 大于或等于(greater or equal) [ $a -ge 1 ]
-le 小于或等于(lesser or equal) [ $a -le 1 ]
  • 字符串测试:[ 操作符 字符串 ]
操作符 说明
-z 字符串内容为空 未定义或者赋予空值的变量将视为空串
-n 是否有字符串
  • 字符串比较:[ 字符串1 操作符 字符串2 ]
操作符 说明
= 字符串内容相同
!= 字符串内容不同,!表示取反的意思
  • 逻辑测试[ 表达式1 ] 操作符 [ 表达式2 ] ...
操作符 说明
-a
&&
逻辑与,而且的意思 操作符前后条件都需成立
-o
| |
逻辑或,或者的意思 只需前后操作符中一个成立即可
! 逻辑否的意思

逻辑测试中还可以使用命令:命令1 操作符 命令2 ...

&&前的表达式或命令均成立时,才执行&&后的命令和表达式;当||前的表达式或命令均不成立时,才执行||后的命令和表达式。(短路原则)

if条件语句

if 条件测试 ; than
	...
elif 条件测试 ; than
	...
else
	...
...
fi

case条件语句

case 变量 in
情况一变量或值|变量或值|...)
    ...(cmd)
    ;;
情况二变量或值|...)
    ...(cmd)
    ;;
...
*)# *号意为任意其他
	...(cmd)
    ;;
esac

注:变量或值只能是单个的,之间用|隔开;对于数组变量$array意为数组的第一个值${array[0]}

shell中的循环语句

for循环

for 变量 in 串行 ; do
	...(cmd)
done

串行:一些字符串的组合,彼此用$IFS所定义的分隔符(如空格符)隔开,这些字符串称为字段

while循环

while 条件测试 ; do
	...(cmd)
done

until循环

until 条件测试 ; do
	...
done

shell标准输入(read)

read命令用于从标准输入读取数值:read 参数 ... 变量名

read常用参数 说明
-a 后跟一个变量,该变量会被认为是个数组,然后给其赋值,默认是以空格为分割符
-d 后面跟一个标志符,其实只有其后的第一个字符有用,作为结束的标准
-p 后面跟提示信息,即在输入前打印提示信息
-e 在输入的时候可以使用命令补全功能
-n 后跟一个数字,定义输入文本的长度,很实用
-r 屏蔽\,如果没有该选项,则\作为一个转义字符,有的话\就是个正常的字符了
-s 安静模式,在输入字符时不在屏幕上显示,例如login时输入密码
-l 后面跟秒数,定义输入字符的等待时间
-u 后面跟fd,从文件描述符中读入,该文件描述符可以是exec新开启的

例如:

#! /bin/bash
read -p "please enter a name." NAME
echo "welcome,$NAME!!!"

原文:https://www.cnblogs.com/yexiaowo/p/shell.html

文章分类
代码人生
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐