变量相关
- 可以使用echo打印变量值,格式如echo $name
- 申明变量采用键值对的方式,如key=value。不能含有空格
- 可以使用unset取消一个变量
- env命令打印出当前的所有环境变量
- set命令打印出当前的所有自定义变量
- 环境变量和自定义变量的区别在于能不能被子进程所采用。当在bash中执行一条命令时,比如说ls -l命令。bash所在进程会fork一个子进程,然后子进程exec跟ls -l命令相关的程序;这时候,如果不去特别指定环境变量,那么子进程默认继承父进程的环境变量,而不继承用户自定义的变量。
- 使用export命令可以使一个自定义变量成为环境变量
- 可以调用read命令(是shell命令,不是系统调用)读取键盘输入
- declare用来申明变量,通用格式如下:declare 【-aixr】variable;-a将后面的变量名申明为一个数组,-i将变量申明为一个整数,-x将后面的变量申明为环境变量,-r表示将变量申明为不可更改,只读类型。
管道相关命令
- cut命令用来提取出一段信息中的一小段,常用的格式为cut -d '分割字符' -f [index]和cut -c start-end。第一种是将一段字符串按照分隔符分成若干段,取出第index段;第二种是以字符为单位,选定一定范围内的字符。通常配合管道一起使用
- grep命令用来分析一整行信息。通用格式为grep [-acinv] [--color=auto] '查找的字符串' filename。-i表示忽略大小写,-a表示将二进制文件看成text的格式,-c统计所找字符串出现的次数,-n输出行号
常用命令
- "#"相当于注释
- 第一行#!/bin/bash表示此脚本所使用的shell是哪一种
- 可以使用$((计算式))的方式来计算加减乘除
- 执行sh脚本时,可以传递参数;这和c相类似,第一个参数表示文件名
- $1-9表示脚本参数
- $0表示脚本名称
- $#表示一共有几个参数
- $?表示一条命令执行完的返回值,返回的是最近一条命令的返回值
- wc命令通常用来一个文件的文本信息,-c表示统计字符,-l表示统计行数
- read命令的几个选项含义如下:-n表示限定输入的字符数,-s表示不显示输入的内容,-p表示可以接收多个参数。比如说要通过read命令接收三个参数:
read -p "请输入三个参数: " arg1 arg2 arg3
- echo命令用于在标准输出上输出后面的所有参数,-n选项表示输出完不换行,-e可以不输出转义字符;当参数中出现以下一些特殊字符时,带-e选项的echo不会输出普通文本,而是按照特殊功能进行显示。
字符 |
作用 |
\a |
发出警告声 |
\b |
删除前一个字符 |
\c |
最后不加上换行符 |
\f |
换行但光标仍停留在原来的位置 |
\n |
换行且光标移至首行 |
\r |
光标移至首行但不换行 |
\t |
插入tab |
"\" |
插入\ |
" |
插入" |
- 系统的环境变量可以使用env命令查看,保存于/etc/profile文件中,这是系统的默认Shell配置文件。在每一个用户登录时会自动执行该文件,所以说这个配置文件对所有的用户都生效。而每个用户可以配置自己的配置文件,一般是$HOME/.bashrc文件。
- 环境变量又分为全局的和局部的。局部环境变量只能用于当前shell,而全局的可以在任意一个shell中使用。
使用命令set可以查看所有本地环境变量,使用export参数可以声明全局环境变量。
- 可以使用declare 命令来声明变量,-i表示声明一个整数,-a定义一个数组,-x设置全局环境变量,-r定义只读变量。比如要声明一个数组,可以这样写
declare -a arr;arr[1]=1;arr[3]=2;
echo ${arr[3]} //输出2
- 使用source命令可以使声明的变量立即生效
- unset命令可以取消一个环境变量
- grep命令的基本格式如下,如果grep命令不指定文件,那么就从标准输入中去读取数据进行匹配。-c选项只显示符合样式的行数,-h选项不显示文件名,-i选项不区分大小写,-n选型显示匹配行及行号,-E关心大小写(默认不区分大小写)。匹配样式中可以用正则表达式且可以查找多个匹配,用|分隔。
grep [选项][匹配样本][文件列表]
- grep常用命令使用示例如下
#文件或者目录搜索
ls -l | grep "dirname"
#文件中查找特定字符
ls -l | grep "filename" | grep "str"
#检索特定进程
ps -aux | grep "processname"
特殊符号和通配符
- 在shell中一部分字符被当做特殊字符,当输出他们的时候,不会输出普通字符,比如说$和\等
- 当我们用单引号去输出参数的时候,就会把单引号里面所有的内容全部当成普通字符
- 当我们用双引号去输出参数的时候,除了$,\等特殊字符之外的字符被当做普通字符输出
- 当我们用倒引号输出的时候,会将倒引号中的字符当做命令去执行,将执行结果返回,比如说下面的语句就打印出了当前工作目录
echo "当前工作目录是:" `pwd`
常用正则表达式 |
作用 |
示例表达式 |
* |
匹配任意个字符,可以为0或多个 |
a*b |
? |
匹配一个字符 |
a?b |
[list] |
匹配list中的一个字符 |
a[abc]b |
[^list] |
匹配除list中的任意一个字符a[^abc]b |
[c1-c2] |
匹配c1到c2之间的所有字符,字符序列必须连续,如a-c |
a[1-5]b |
. |
匹配任意一个字符 |
.*abc |
x\{m\} |
字符x重复出现m次 |
x\{3\} |
x\{m,\} |
字符x至少出现m次 |
x\{3,\} |
x\{m,n\} |
字符x重复出现m到n次 |
x\{2,5\} |
逻辑控制语句
#单个条件判断
if [条件判断];then
处理
fi
#多个条件判断
if [条件1]
then
处理1
elif[条件2]
then
处理2
else
处理3
fi
- 测试命令的基本结构如下,expression是表达式,表达式可以是数字,字符串,文件属性和各种类型的比较。test命令的返回值只能是整数,不能是其他类型。
test expression
- 另外可以使用[]代替test命令,对于一般的逻辑条件判断效果一样;而test命令可以用来判断一些文件的属性,test命令的关于一些文件的选项如下表
test命令选项 |
作用 |
-e |
判断文件是否存在 |
-f |
判断文件是否存在且是否是文件 |
-d |
判断文件是否存在且是否是目录文件 |
-c |
判断文件是否存在且是否是设备文件 |
-S |
判断文件是否存在且是否是socket文件 |
-p |
判断文件是否存在且是否是管道文件 |
-L |
判断文件是否存在且是否是链接文件 |
-nt |
test file1 -nt file2判断文件1是否比文件2新 |
-ot |
test file2 -ot file2判断文件1是否比文件2旧 |
-rwx |
test -[rwx] file判断文件相关的读写执行权限 |
- 关于条件判断时经常会涉及一些整数之间的比较,不能使用大于小于号,因为bash会误以为是重定向符号,常见的符号如下表
符号 |
作用 |
test n1 -eq n2 |
判断数字1和数字2是否相等 |
test n1 -ge n2 |
判断数字1是否大于等于数字2 |
test n1 -gt n2 |
判断数字1是否大于数字2 |
test n1 -le n2 |
判断数字1是否小于等于数字2 |
test n1 -lt n2 |
判断数字1是否小于数字2 |
test n1 -ne n2 |
判断数字1是否不等于数字2 |
运算符 |
作用 |
!exp |
如果exp为假,则返回真 |
exp1 -a exp2 |
如果两个表达式同事为真,返回真 |
exp1 -o exp2 |
如果两个表达式中有一个为真,返回真 |
- case多条件分支结构,示例代码如下,*)相当于default
echo -n "输入一个数:"
read n
case $n in
1)...
2)...
....
5)...
*)...
esac
select choice in 1 2 3 4 5
do
break
done
echo "you choose No.$choice"
循环结构
for 变量 in 列表
do
commands
done
#示例,用来遍历目录
for file in $(ls /home)
do
...
done
for((exp1;exp2;exp3))
do
...
done
#示例
for((i=1;i<=10;i++))
do
echo $i
done
while test expression
do
...
done
#示例
index=1
while [ $index -le 6 ]
do
echo $index
let index++
done
- 可以使用break跳出循环。另外,break n表示跳出n层循环,默认为1;continue继续下一次循环,与类c语言相似
函数和数组
- 函数的定义格式如下,函数名称在同一个脚本文件中必须是唯一的,在函数调用时,bash会按照顺序去执行语句
function name
{
commands
}
#或者可以省略function关键字,用括号代替
name()
{
commands
}
- 调用函数的方式与调用命令类似,直接写函数名就行,后面可以带上参数。这与在命令行执行命令或者调用可执行程序类似。在函数中使用传进来的参数的方法和调用脚本参数类似。大致规则如下
- $0表示函数名
- $1表示第一个参数,以此类推且最多能传进来9个参数
- $#表示一共传进来几个参数
- 同样的,$?记录最后执行的函数的返回值;而函数在不显示返回值的时候,默认返回函数中最后一条调用的命令的返回值;如果想要自定义返回值,使用关键字return,使用return命令的返回值只能在0-255之间
- 有关同一个脚本范围内的局部变量和全局变量,是这样规定的:不显示调用local关键字声明的变量就是全局变量;相反,通过local声明的变量就是局部变量,只能在函数范围内使用
- 数组的相关规则如下
#数组的声明方式如下
arr=(1,2,3,4,5)
#也可以使用declare关键字声明
declare -a arr=(1,2,3,4,5)
#使用一个数组变量的格式,下标从0开始,shell中的数组没有越界的概念。如果超过了范围,输出为空
${arr[1]}
#表示数组的所有元素
${arr[*]}
#表示数组的长度
${#arr[*]}
- 当调用函数传入数组参数时,必须将数组中每个元素一个个传进去,常常使用"${arr[*]}"的格式
- 在函数内部使用数组时,需要声明一个局部数组变量去接收数组,才能使用
- 当数组作为函数返回值时,需要使用echo命令将数组中的每个元素返回(上面说过,如果没有return命令,默认返回最后一条命令的返回值);并且在使用这个返回的数组之前,同样需要声明数组变量去接收,然后才能使用。示例代码如下
arr=(1 2 3 4 5)
echo "arr[*]=${arr[*]}"
echo "the length of arr = ${#arr[*]}"
echo "arr[1]=${arr[1]}"
func1()
{
local temp=($1)
echo "total args = $#"
echo "the array arg:${temp[*]}"
echo "the array arg:$@"
return 0
}
func2()
{
local old=($1)
for((i=0;i<${#old[*]};i++))
{
old[$i]=$[${old[$i]}*2]
}
echo ${old[*]}
}
echo "函数中接收数组参数并输出"
func1 "${arr[*]}"
echo "函数中接受数组参数并将原值翻倍再返回回来输出"
newarr=`func2 "${arr[*]}"`
echo "newarr=${newarr[*]}"
文件处理相关命令
- 一个外部设备首先需要挂载才能进行读取,挂载用的命令是mount,-t指定文件系统类型,通常不需要指定,操作系统会自动识别。一般格式如下,dest为指定的挂载目录,一般挂载目录都是新创建的空目录,因为当目录上新挂载一个文件系统时,该目录下的原文件都会被隐藏直到卸载该设备才会重新恢复。
mount /dev/sdax dest
- fdisk命令可以查看电脑上的硬盘信息,以下命令可以查看所有硬盘分区信息
fdisk -l
umount /dev/sdax dest
- 在执行一个shell命令行时,自动打开三个标准文件,标准输入,标准输出和标准出错。对应的文件描述符分别为0,1,2
- 事实上,命令行就是一个进程;对于每一个进程,都有一个对应的文件描述符表,里面存放着进程的所有打开文件的文件描述符,而一个进程在初始状态下,自动会打开0,1,2三个文件描述符。
- 输出重定向(>)首先会将文件截断为0,然后才向里面输出;相对的,追加重定向(>>)会在文件末尾接着输出
- 1>表示重定向标准输出,2>表示重定向标准出错,&>表示将标准输出和标准出错合并重定向