shell
简介
Shell就是一个命令行解释器,它的作用就是遵循一定的语法将输入的命令加以解释并传给系统。它为用户提供了一个向Linux发送请求以便运行程序的接口系统级程序,用户可以用Shell来启动、挂起、停止甚至是编写一些程序。 Shell本身是一个用C语言编写的程序,它是用户使用Linux的桥梁。Shell既是一种命令语言,又是一种程序设计语言(就是所说的shell脚本)。而实际中,最常用的是shell script。换一种说法也就是,shell script是利用shell的功能所写的一个程序,这个程序是使用纯文本文件,将一些shell的语法与指令写在里面,然后用正规表示法,管道命令以及数据流重导向等功能,以达到我们所想要的处理目的。
语法
格式
#!
shell 脚本文件开头通过 #!定义使用的编译器类别
#! /bin/bash
Linux 的 Shell 种类众多,常见的有:
- Bourne Shell(
/usr/bin/sh或/bin/sh) - Bourne Again Shell(
/bin/bash) - C Shell(
/usr/bin/csh) - K Shell(
/usr/bin/ksh) - Shell for Root(
/sbin/sh)
注解
注解实现
#--------------------------------------------------------
#
# 这部分是注解,文件解析的时候会默认忽略这部分内容
#
#--------------------------------------------------------
echo "这个是正文。" # 你可以添加独立的,也可以在语句之后添加
:<<`
asdfasdf
asdf
asdf
`
:<<EOF
ASDFASDFASDFASF
EOF
:<<!
ASDFASDFASD
!
# 上面三个是多行注释,<<tag...tag 符号代表 Here Ducument 重定向方式
变量的定义及使用
变量的定义
val=123
cal="123" # 需要注意的是等号的两边不能有空格
变量的使用
temp=$val
temp="abc"$val
temp="abc"${val} # 变量的使用可以是 $val 也可以 ${val},推荐后一种,这样可以明确变量边界
关于引号
类似于PHP中的引号规则,双引号相较于单引号有更多的解析能力,可以解析字符中的变量、转义字符等。
echo "aaa${val}" # aaa123
echo 'aaa${val}' # aaa#{val}
echo 'aaa'${val} # aaa123
只读属性
readonly val # 只读属性不能修改
删除变量
unset val # 删除变量 [-fnv] f:对应的方法 n:对应的拥有nameref属性的变量,引用变量不会 v:对应的自身和引用变量
变量类型
- 局部变量 仅当前shell实例可以进行访问
- 环境变量 除shell实例之外,启动的程序也是可以进行访问的
- shell变量 定义的用于保证shell运行的变量,包括局部和环境两种
字符串
单引号
- 单引号内的任何字符都会进行原样输出,无法使用变量
- 多个单引号可以进行字符串的拼接
双引号
- 双引号内可以使用转义字符等特殊字符,可以引用变量
- 多个双引号可以进行字符串的拼接
拼接
- 通过两个字符串拼接
string = 'aaa'${val}'bbbbb' - 可以通过在双引号内使用变量
string = "aaa${val}bbbb"
长度
可以通过 ${#val} 的方式,输出字符串 val 的长度
截取
通过 ${val:start:length} 的方式对val 进行截取,截取时不包括 start 字符
查找
通过 ` expr index "$string" io ` 对字符串string 进行查找,io 的意思是搜索i 或o,谁先出现就查谁
数组
创建
数组可以通过
-
list = (a b c ...) -
list = (abc...) -
list[0] = alist[n] = b这样定义的好处是,下标不需要连续,也没有上限
读取
数组的读取直接通过下标可以获得${list[index]}
获取全部可以用 ${list[@]} 或者 ${list[*]}
长度
通过 ${#list[@]} 或者 ${#list[*]} 获取整个数组的长度,某个元素的长度可以用 ${#list[index]}
参数传递
$n
通过$n 可以获取到命令行参数,所有的。
$#
获取传入参数的个数
$* 和 $@
他们都必须搭配""使用,不同的是$* 将传入的所有参数都作为一个整体,而$@ 则是将参数作为一个数组。
$$
当前运行的进程ID
$!
后台运行的最后一个进程ID
$-
作用同 set 命令相似
$?
命令退出的状态,0 为正常,其他为执行有问题。
- 如果参数中有空格,可以使用引号括起来,便于脚本识别和使用
- 中括号的使用,中括号和其中的参数应该有空格隔开
运算符
shell 支持多种运算编程:
- 算术运算
- 布尔运算
- 关系运算
- 字符串运算
- 文件测试运算
原生的bash不支持简单的数学运算,可以通过 awk 和 expr 命令执行
expr
expr 是一个表达式计算工具
- 表达式和运算符之间需要有空格
- 需要被
` `包裹才可以使用
运算符
算术运算符
-
+ -
- -
*`expr $a \* $b`乘法需要用转义符进行处理才能使用 -
/ -
% -
=赋值
-
!=[ $a != $b ]注意中括号和参数之间的空格 -
==同上
关系运算符
关系运算符只能适用数字,除非字符串的内容是数字,不然不适用。
-
-eq相等equal -
-gt大于greater than -
-lt小于less than -
-ge大于等于greater than and equal to -
-le小于等于less than and equal to -
-ne不等于not equal使用的时候通过
[]包含进行使用
布尔运算符
-
!非 -
-oor -
-aand使用的时候也是通过
[]包含使用
逻辑运算符
-
&& -
||使用的时候需要搭配
[[ ]]包含使用
字符串运算符
-
=是否相等 -
!=是否不等 -
-n长度是否不为零 -
-z长度是否为零 -
$是否不为空搭配
[]包含使用
文件测试运算符
文件测试运算检测Unix文件的属性。
| 操作符 | 说明 | 举例 |
|---|---|---|
| -b file | 检测文件是否是块设备文件,如果是,则返回 true。 | [ -b $file ] 返回 false。 |
| -c file | 检测文件是否是字符设备文件,如果是,则返回 true。 | [ -c $file ] 返回 false。 |
| -d file | 检测文件是否是目录,如果是,则返回 true。 | [ -d $file ] 返回 false。 |
| -f file | 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 | [ -f $file ] 返回 true。 |
| -g file | 检测文件是否设置了 SGID 位,如果是,则返回 true。 | [ -g $file ] 返回 false。 |
| -k file | 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 | [ -k $file ] 返回 false。 |
| -p file | 检测文件是否是有名管道,如果是,则返回 true。 | [ -p $file ] 返回 false。 |
| -u file | 检测文件是否设置了 SUID 位,如果是,则返回 true。 | [ -u $file ] 返回 false。 |
| -r file | 检测文件是否可读,如果是,则返回 true。 | [ -r $file ] 返回 true。 |
| -w file | 检测文件是否可写,如果是,则返回 true。 | [ -w $file ] 返回 true。 |
| -x file | 检测文件是否可执行,如果是,则返回 true。 | [ -x $file ] 返回 true。 |
| -s file | 检测文件是否为空(文件大小是否大于0),不为空返回 true。 | [ -s $file ] 返回 true。 |
| -e file | 检测文件(包括目录)是否存在,如果是,则返回 true。 | [ -e $file ] 返回 true。 |
其他检查符:
- -S: 判断某文件是否 socket。
- -L: 检测文件是否存在并且是一个符号链接。
echo
用于文字的输出。
echo string 可以用来输出string字符,string可以是单引号、双引号,也可以是指令。单双引号的用法没变,指令需要用` `符号包含,显示执行的结果。也可以通过>符号将结果输出到指定文件中,eg:echo "this is string" > file.txt。如果想要对输出结果进行换行显示,需要增加-e属性,用于开启转义,eg:echo "this is \n" 换行;echo "this si \c" 不换行
printf
printf 作为shell的另一种输出方式,对比echo,它具有更好的移植性、更强的功能。
test
用于检测某个条件是否成立,它可以检测数字、字符串、文件。
test 可以代替运算符使用过程中的[]符号。
流程控制
if...elif...else...fi
流程命令可以写成多行也可以写成一行,每个逻辑段落用;进行分割。
if test $[a]
then
......
elif test $[b]
then
......
else
......
fi
for
for var in list
do
......
done
也可以
for ((i=0;i<5;i++)) # 通常情况下 shell 变量调用需要加 $,但是 for 的 (()) 中不需要
do
......
done
# 变形
val = 5;
for (( $val < 10 )) # 使用的时候需要通过 `$` 修饰
do
echo "。。。。。。"
let "val++" # let 方法可以不用 `$` 修饰,使用变量
done
for ((arg;arg1:next))
do
......
done
写成一行
for var in list;do;......;done;
while
while ((...))
do
......
done
无限循环:
while :
do
......
done
while true
do
......
done
for ((;;))
until
与while刚好相反,until直到判断为true,停止循环。
until test $[...]
do
......
done
case
case $a in
1)
......
;; # break 一致
*) # default 值
......
;;
esac
结束循环
与其他语言类似,结束循环可以使用break和continue
break # 结束循环并推出
continue # 结束当前循环
自定义函数
可以通过自定义一个函数,进行全局调用。不过,必须要先定义才能使用,所以函数应该优先放在开始的地方。
# 定义的方式可以带 functino 字样,也可以不带
functino damo() {
......
return int; # 返回信息通过 return 返回一个数值 [0-255]
}
damo() {
...... # 也可以不用 return 默认返回最后一条语句的执行结果
}
damo # 调用函数直接通过函数名调用
damo 1 3 4 5 6 # 调用的时候也可以带参数调用,函数内通过 $1 $2... 方式进行获取,第十个参数开始,需要通过${10} 的方式获取
echo $? # $? 可以用来获取上一条语句的执行结果,如果上一条语句是执行函数,将会返回函数的返回值
输入 /输出重定向
默认情况下,Unix 系统会从一个标准输入的地方获得一个输入,并将结果输出到标准输出的地方,而这两个地方就是你的终端。如果想要修改输入、输出的位置,那就需要进行重定向。
-
>输入重定向<输入重定向 -
>>输出追加 -
>&输出合并<&输入合并 -
<<tag以tag开始到tag结束,中间的内容作为输入command <<tag # tag 可以是任意字符 ...... tag # tag 顶格,前后都没有内容,包括空格和table
文件描述符
Unix 在执行命令的时候会打开三种文件:输入文件(0)、输出文件(1)、错误文件(2)。描述符可以在语句中明确操作的文件类型。
command > file # 默认情况下,这条语句代表将输出文件重定向到 file 中
command 2> file # 通过添加文件描述符,可以将特定文件进行重定向输出
command > file 2>&1 # 将输出文件和错误文件合并之后输出到 file
/dev/null
这个文件是一个比较特殊的文件,它接受的任何内容都会被丢弃,也不会被查到任何信息。所以可以通过重定向到这个文件,用来达到 无输出的目的。
command > /dev/null 2>&1
包含文件
脚本中可以引用其他的文件,将其内容引入到自己文件中,可以等同看作文件的合并。
. filePath # 通过 . 引入
source filePath # 通过 source 引入
被引入的文件可以没有可执行权限,文件中定义的变量也可以在本地使用。
学习资源来自菜鸟教程(https://www.runoob.com/linux/linux-shell-io-redirections.html)

被折叠的 条评论
为什么被折叠?



