Shell参考项

目录:

特殊的shell变量

变量含义
$0脚本名字
$1位置参数 #1
$2 - $9位置参数 #2 - #9
${10}位置参数 #10
$#位置参数的个数
"$*"所有的位置参数(作为单个字符串) *
"$@"所有的位置参数(每个都作为独立的字符串)
${#*}传递到脚本中的命令行参数的个数
${#@}传递到脚本中的命令行参数的个数
$?返回值
$$脚本的进程ID(PID)
$-传递到脚本中的标志(使用set)
$_之前命令的最后一个参数
$!运行在后台的最后一个作业的进程ID(PID)

* 必须被引用起来, 否则默认为"$@".


测试操作: 二元比较
操作描述-----操作描述





算术比较

字符串比较
-eq等于
=等于



==等于
-ne不等于
!=不等于
-lt小于
\<小于 (ASCII) *
-le小于等于


-gt大于
\>大于 (ASCII) *
-ge大于等于





-z字符串为空



-n字符串不为空





算术比较双括号(( ... ))结构


>大于


>=大于等于


<小于


<=小于等于



* 如果在双中括号 [[ ... ]] 测试结构中使用的话, 那么就不需要使用转义符\了.


文件类型的测试操作

操作

测试条件操作测试条件
-e文件是否存在-s文件大小不为0
-f是一个标准文件

-d是一个目录-r文件具有权限
-h文件是一个符号链接-w文件具有权限
-L文件是一个符号链接-x文件具有执行权限
-b文件是一个块设备

-c文件是一个字符设备-g设置了sgid标记
-p文件是一个管道-u设置了suid标记
-S文件是一个socket-k设置了"粘贴位"
-t文件与一个终端相关联





-N从这个文件最后一次被读取之后, 它被修改过F1 -nt F2文件F1比文件F2 *
-O这个文件的宿主是你F1 -ot F2文件F1比文件F2 *
-G文件的组id与你所属的组相同F1 -ef F2文件F1和文件F2都是同一个文件的硬链接 *




!"非" (反转上边的测试结果)


* 二元操作符(需要两个操作数).


参数替换和扩展
表达式含义
${var}变量var的值, 与$var相同


${var-DEFAULT}如果var没有被声明, 那么就以$DEFAULT作为其值 *
${var:-DEFAULT}如果var没有被声明, 或者其值为空, 那么就以$DEFAULT作为其值 *


${var=DEFAULT}如果var没有被声明, 那么就以$DEFAULT作为其值 *
${var:=DEFAULT}如果var没有被声明, 或者其值为空, 那么就以$DEFAULT作为其值 *


${var+OTHER}如果var声明了, 那么其值就是$OTHER, 否则就为null字符串
${var:+OTHER}如果var被设置了, 那么其值就是$OTHER, 否则就为null字符串


${var?ERR_MSG}如果var没被声明, 那么就打印$ERR_MSG *
${var:?ERR_MSG}如果var没被设置, 那么就打印$ERR_MSG *


${!varprefix*}匹配之前所有以varprefix开头进行声明的变量
${!varprefix@}匹配之前所有以varprefix开头进行声明的变量

* 当然, 如果变量var已经被设置的话, 那么其值就是$var.


字符串操作
表达式含义
${#string}$string的长度


${string:position}$string中, 从位置$position开始提取子串
${string:position:length}$string中, 从位置$position开始提取长度为$length的子串


${string#substring}从变量$string的开头, 删除最短匹配$substring的子串
${string##substring}从变量$string的开头, 删除最长匹配$substring的子串
${string%substring}从变量$string的结尾, 删除最短匹配$substring的子串
${string%%substring}从变量$string的结尾, 删除最长匹配$substring的子串


${string/substring/replacement}使用$replacement, 来代替第一个匹配的$substring
${string//substring/replacement}使用$replacement, 代替所有匹配的$substring
${string/#substring/replacement}如果$string前缀匹配$substring, 那么就用$replacement来代替匹配到的$substring
${string/%substring/replacement}如果$string后缀匹配$substring, 那么就用$replacement来代替匹配到的$substring




expr match "$string" '$substring'匹配$string开头的$substring*的长度
expr "$string" : '$substring'匹配$string开头的$substring*的长度
expr index "$string" $substring$string中匹配到的$substring的第一个字符出现的位置
expr substr $string $position $length$string中从位置$position开始提取长度为$length的子串
expr match "$string" '\($substring\)'$string的开头位置提取$substring*
expr "$string" : '\($substring\)'$string的开头位置提取$substring*
expr match "$string" '.*\($substring\)'$string的结尾提取$substring*
expr "$string" : '.*\($substring\)'$string的结尾提取$substring*

* $substring是一个正则表达式.


一些结构的汇总
表达式解释


中括号
if [ CONDITION ]测试结构
if [[ CONDITION ]]扩展的测试结构
Array[1]=element1数组初始化
[a-z]正则表达式的字符范围


大括号
${variable}参数替换
${!variable}间接变量引用
{ command1; command2; . . . commandN; }代码块
{string1,string2,string3,...}大括号扩展




圆括号
( command1; command2 )子shell中执行的命令组
Array=(element1 element2 element3)数组初始化
result=$(COMMAND)在子shell中执行命令, 并将结果赋值给变量
>(COMMAND)进程替换
<(COMMAND)进程替换


双圆括号
(( var = 78 ))整型运算
var=$(( 20 + 5 ))整型运算, 并将结果赋值给变量


引号
"$variable""弱"引用
'string'"强"引用


后置引用
result=`COMMAND`在子shell中运行命令, 并将结果赋值给变量

"保留的"退出码

退出码的值含义例子注释
1通用错误let "var1 = 1/0"各种各样的错误都可能使用这个退出码, 比如"除0错误"
2shell内建命令使用错误(Bash文档上有说明)
很少看到, 通常情况下退出码都为1
126命令调用不能执行
程序或命令的权限是不可执行的
127"command not found"
估计是$PATH不对, 或者是拼写错误
128exit的参数错误exit 3.14159exit只能以整数作为参数, 范围是0 - 255(见脚注)
128+n信号"n"的致命错误kill -9 脚本的$PPID$? 返回137(128 + 9)
130用Control-C来结束脚本
Control-C是信号2的致命错误, (130 = 128 + 2, 见上边)
255*超出范围的退出状态exit -1exit命令只能够接受范围是0 - 255的整数作为参数

重要的文件

启动文件

这些文件包含别名和环境变量, 正是这些别名和环境变量才使得Bash可以作为一个用户shell来运行, 当系统初始化之后, 这些别名和变量也可被其他的的Bash脚本调用.

  • /etc/profile

    系统范围的默认值, 大部分用来设置环境(所有的Bourne类型的shell, 而不仅仅是Bash[1])

  • /etc/bashrc

    特定于Bash的, 系统范围函数与别名

  • $HOME/.bash_profile

    用户定义的, 环境默认设置, 在每个用户的home目录下都可找到(本地副本保存在/etc/profile)

  • $HOME/.bashrc

    用户定义的Bash初始化文件, 可以在每个用户的home目录下找到(本地副本保存在/etc/bashrc). 只有交互式的shell和用户脚本才会读取这个文件. 

登出文件

  • $HOME/.bash_logout

  • 用户定义的指令文件, 在每个用户的home目录下找到. 在登出(Bash)shell的时候, 这个文件中的命令就会得到执行.

注意事项

[1]

不能应用于cshtcsh, 或那些与经典Bourne shell无关的shell(也就是说那些不是派生自sh的shell).

重要的系统目录

每位系统管理员或者是编写系统管理脚本的人员都应该对这些系统目录非常熟悉.

  • /bin

    二进制(可执行文件). 基本的系统程序和工具(比如bash).

  • /usr/bin [1]

    更多的系统二进制可执行文件.

  • /usr/local/bin

    一些局部于特定机器的杂项二进制可执行文件.

  • /sbin

    系统二进制可执行文件. 基本的系统管理程序和工具(比如fsck).

  • /usr/sbin

    更多的系统管理程序和工具.

  • /etc

    其他. 系统范围的配置脚本.

    其中比较有趣的文件是/etc/fstab(文件系统表), /etc/mtab(挂载文件系统表), 还有文件/etc/inittab.

  • /etc/rc.d

    启动脚本, 适用于红帽及其派生的Linux发行版.

  • /usr/share/doc

    安装包的文档.

  • /usr/man

    系统范围的man页.

  • /dev

    设备目录. 物理设备和虚拟设备的入口(但不是挂载点)

  • /proc

    进程目录. 包含关于运行进程和内核参数的统计信息与其他信息

  • /sys

    系统范围的设备目录. 包含关于设备和设备名称的统计信息与其他信息. 这是在Linux 2.6.X内核版本上新添加的目录.

  • /mnt

    挂载. 挂载硬驱动分区的目录, 比如/mnt/dos, 和物理驱动器. 在比较新的Linux发行版中, /media目录已经成为了I/O设备的首选挂载点.

  • /media

    在比较新的Linux发行版中, I/O设备的首选挂载点, 比如CD ROM或USB flash驱动器.

  • /var

    可变的(可修改的)系统文件. 这是一个包罗万象的"杂项"目录, 用于保存Linux/UNIX机器运行时产生的各种数据.

  • /var/log

    系统范围的日志文件.

  • /var/spool/mail

    用户的假脱机邮件(mail spool).

  • /lib

    系统范围的库文件.

  • /usr/lib

    更多系统范围的库文件.

  • /tmp

    系统临时文件.

  • /boot

    系统引导目录. 内核, 模块链接, 系统镜像, 和引导管理器都放在这.


    Warning

    如果在这个目录下修改文件, 可能会导致系统不能启动.

注意事项

[1]

早期的UNIX系统一般都有两个磁盘设备, 一个是速度快但容量小的硬盘(主要包含/, 即根目录), 另一个磁盘容量大, 但是速度慢(主要包含/usr目录和其他分区). 所以, 使用频率最高的程序和工具都放到小而快的磁盘中, 也就是放到/bin中, 而其他的东西都放到慢磁盘上, 即/usr/bin中.

其他的类似的东西也是按照这种方式进行分类的, 比如/sbin/usr/sbin/lib/usr/lib, 等等.

将DOS批处理文件转换为Shell脚本

相当多的在PC上学习脚本的程序员都在运行DOS. 事实上, 残废的DOS批处理文件语言还是可以编写出一些比较强大的脚本来的, 虽然它们一般都需要借助于外部的工具. 所以说, 某些时候, 我们还是需要将老式的DOS批处理文件转换为UNIX shell脚本. 一般来说, 做这种事情并不困难, 因为DOS批处理文件操作不过是等价的shell脚本的一个受限子集.


批处理文件关键字 / 变量 / 操作符, 和等价的shell符号
批处理文件操作符Shell脚本等价符号含义
%$命令行参数前缀
/-命令选项标记
\/目录路径分隔符
===(等于)字符串比较测试
!==!!=(不等)字符串比较测试
||管道
@set +v不打印当前命令
**文件名"通配符"
>>文件重定向(覆盖)
>>>>文件重定向(附加)
<<重定向stdin
%VAR%$VAR环境变量
REM#注释
NOT!取反
NUL/dev/null"黑洞"用来阻止命令输出
ECHOecho打印(Bash中有更多选项)
ECHO.echo打印空行
ECHO OFFset +v不打印后续的命令
FOR %%VAR IN (LIST) DOfor var in [list]; do"for"循环
:LABEL没有等价物(多余)标签
GOTO没有等价物(使用函数)跳转到脚本的另一个位置
PAUSEsleep暂停或等待一段时间
CHOICEcase or select菜单选择
IFifif条件语句
IF EXIST FILENAMEif [ -e filename ]测试文件是否存在
IF !%N==!if [ -z "$N" ]参数"N"是否存在
CALLsource命令或.(点操作符)"include"另一个脚本
COMMAND /Csource命令或.(点操作符)"include"另一个脚本(与CALL相同)
SETexport设置一个环境变量
SHIFTshift左移命令行参数列表
SGN-lt或-gt(整形)符号
ERRORLEVEL$?退出状态
CONstdin"控制台"(stdin)
PRN/dev/lp0(一般的)打印设备
LPT1/dev/lp0第一个打印设备
COM1/dev/ttyS0第一个串口

批处理文件一般都包含DOS命令. 我们必须把它转换为UNIX的等价命令, 这样我们才能把批处理文件转换为shell脚本文件.


DOS命令与UNIX的等价命令
DOS命令UNIX等价命令效果
ASSIGNln链接文件或目录
ATTRIBchmod修改文件权限
CDcd更换目录
CHDIRcd更换目录
CLSclear清屏
COMPdiff, comm, cmp文件比较
COPYcp文件拷贝
Ctl-CCtl-C中断(信号)
Ctl-ZCtl-DEOF(文件结束)
DELrm删除文件
DELTREErm -rf递归删除目录
DIRls -l列出目录内容
ERASErm删除文件
EXITexit退出当前进程
FCcomm, cmp文件比较
FINDgrep在文件中查找字符串
MDmkdir新建目录
MKDIRmkdir新建目录
MOREmore分页显示文本文件
MOVEmv移动文件
PATH$PATH可执行文件的路径
RENmv重命名(移动)
RENAMEmv重命名(移动)
RDrmdir删除目录
RMDIRrmdir删除目录
SORTsort排序文件
TIMEdate显示系统时间
TYPEcat将文件输出到stdout
XCOPYcp(扩展的)文件拷贝
Note

事实上, 几乎所有的UNIX和shell操作符, 还有命令都有许多的选项, 对比DOS和批处理文件来说, 它们要强大的多. 许多DOS批处理文件都需要依靠辅助工具, 比如ask.com, 这是一个比read命令差很多的类似副本.

DOS对于文件名通配符扩展支持的非常有限, 并且很不完整, 仅仅识别*?.

将DOS批处理文件转换为sehll脚本, 通常是一件很简单的事情, 而且转换的结果通常都比原始的批处理文件好.

摘自:高级Bash脚本编程指南: 一本深入学习shell脚本艺术的书籍

参考:Shell学习宝典

anzhihe 安志合个人博客,版权所有 丨 如未注明,均为原创 丨 转载请注明转自:https://chegva.com/3775.html | ☆★★每天进步一点点,加油!★★☆ | 

您可能还感兴趣的文章!

发表评论

电子邮件地址不会被公开。 必填项已用*标注