Shell使用

基本语法

变量

变量的使用

生成变量时必须注意,变量=前后不能有空格。

读取变量时需要在变量前加$美元符,或者${}美元符加花括号,使用花括号为了帮助解释器识别变量的边界。

示例:

name="DonYau"
echo $name
echo ${name}
复制代码

与此同时可以通过${#name}获取变量的长度

read 获取用户的输入

read命令从标准输入(键盘)或另一个文件描述符中接受输入。在收到输入后,read命令 会将数据放进一个变量。使用read时,可以设置-t n来设置一个定时器,当计时器过期后,read会返回一个非零退出状态码

例如:

echo -n "Enter your age:"
read age
复制代码

数组

格式:names=(value1 ... valuen) 数组元素之类采用空格隔离

可以使用索引值对数组进行赋值:

names[0]=name
names[1]=age
复制代码

读取数组的某个值:

echo ${names[0]}
index=1
echo ${name[$index]}
复制代码

显示整个数组的值:

echo ${name[*]}
echo ${name[@]}
复制代码

删除数组中的某个值:

unset name[1]
//删除整个数组
unset name[*]
复制代码

获取数组的长度

echo ${#name[*]}
echo ${#name[@]}

输出数组的所有值
echo ${name[*]}
echo ${name[@]}
复制代码

test命令

test命令可以判断三类条件:

  1. 数值比较
  2. 字符串比较
  3. 文件比较

数值比较

运算符 含义
-eq 等于
-ne 不等于
-gt 大于
-lt 小于
-ge 大于或者等于
-le 小于或者等于

例如:

value1=10
if [ $value1 -gt 5 ];then
    echo "$value1 大于 5"
fi
复制代码

字符串比较

运算符 含义
str1 = str2 检查str1是否和str2相同
str1 != str2 检查str1是否和str2不相同
str1 < str2 检查str1是否比str2小
str1 > str2 检查str1是否和str2大
-n 检查str1的长度是否非0
-z 检查str1的长度是否为0

注意:在字符串使用比较符时,大于号和小于号必须转义,否则shell会把它们当作重定向符号

例如:

value1=a
value2=b
if [ $value1 = $value2 ];then
echo "两个值是否相等"
fi

if [ $value1 \> $value2 ];then
echo "value1 大于 values"
fi
复制代码

文件比较

运算符 含义
-d 文件是否存在,且为目录
-e 文件是否存在
-f 文件是否存在,且为普通文件
-r 文件是否可以读
-s 文件存在,且大于0
-w 文件存在且可写
-x 文件存在且可执行

复合条件

  1. [ condition1 ] && [ condition2 ]
  2. [ condition1 ] || [ condition2 ]

括号的使用

双括号

双括号允许在比较过程中使用高级数学表达式

例如:

value=10
if ((  $value ** 2 > 19 )); then
	echo "大于19"
fi
复制代码

双方括号

双方括号里的expression使用了test命令中采用的标准字符串比较。但它提供了test命 令未提供的另一个特性——模式匹配

\\使用了双等号==,双等号将右边的字符串(*e*)视为一个模式, 并应用模式匹配规则
value="shell find"
if [[ $value == *e* ]]; then
	echo "符合"
fi
复制代码

使用结构化命令

base shell的if语句会运行if后面的命令,如果该命令的退出状态码是0,这命令成功运行,位于then部分的命令就会被执行。如果退出状态码是其他值,then部分的命令就不会被执行。

if-then

格式:

if command
then
    command
fi
复制代码

if-then-else

格式:

if command
then
    commands
else
    commands
fi
复制代码

if-then-elif

if command
then
    command
elif command
then command
    command
fi
复制代码

case

例如:

value=2
case $value in
1 | 2)
echo "1或者2";;
3)
echo  "3";;
*)
echo "other";;
esac
复制代码

for

格式:

for var in list
do
    commands
done
复制代码

默认情况下,base shell会将空格制表符换行符当作字段分隔符。

更改字段分隔符

\\定义单个IFS字符
IFS=$'\n'
\\定义多个IFS字符
IFS=$'\n':;
复制代码

while

格式:

while test command
do
    other commands
done
复制代码

循环的输出

在shell脚本中,可以对循环的输出使用管道或进行重定向。这可以通过在done命令之后添加一个处理命令来实现。

例如:

for (( i = 1; i < 10; i++ ))
do
   echo "The number is $a"
done > test.txt

复制代码

函数

函数定义

在shell中使用函数时,必须先定义函数,否则会报错误。如果重新定义了函数,新定义的函数会覆盖原函数,并且不会产生任何错误。

格式:

//第一种
function name {
    commands
}
//第二种
name() {
    commands
}
复制代码

函数变量

函数内部使用的任何变量都可以被声明成局部变量。要实现这 一点,只要在变量声明的前面加上local关键字,该关键字保证了变量只局限在该函数中。倘若不使用local关键字,即使是在函数中申明的变量,在外部也可以访问。

函数参数

函数可以使用标准的参数环境变量来表示命令行上传给函数的参数。在函数内部,通过$#获取参数的个数,$0获取函数的名称,$1获取第一个参数,$2获取第二个参数,以此类推

例如:

function log() {
	echo $0
	echo $#
	echo $1
	echo $2
}

log a 2
复制代码

将数组变量当作单个参数传递的话,将不会起作用,函数只会取数组变量的第一个值。因此,可以将该数组变量的值分解成单个的值,然后将这些值作为函数参数使用。在函数内部,可以将所有的参数重新组合成一个新的变量。

例如:

function log() {
	local a
	a=$(echo "$@")
	echo ${a[*]}
}

array=(1 2 3 4 5)
log ${array[*]}
复制代码

函数返回值

每个函数都有返回状态码。默认情况下,函数的退出状态码是函数中最后一条命令的返回退出状态码。可以使用$?来确定函数的退出状态码。不建议使用默认的函数状态码,因为最后一条命令运行成功不代表中间的命令都能运行成功。

函数的返回值必须小于255,任何大于256的值都会产生一个错误的值。

介于以上情况,采用另外一种输出方式,例如:

function log() {
    echo 300
}

result=$(log)

echo $result
复制代码

若要从函数中返回数组时,可以使用echo按正确的顺序输出单个数组值。

例如:

function log() {
	local a=(1 2 3 4 5)
	echo ${a[*]}
}

result=$(log)
echo $result
复制代码

基本操作

echo 打印指令

输出命令一般有三个格式:

  1. 直接输出
  2. 单引号概括输出
  3. 双引号概括输出

单引号内无法读取变量的值,例如

age=18
echo '$age'
$age
复制代码

当双引号概括输出时,若读取变量后直接拼接字符串,需要使用${}方式读取变量,例如:

age=18
echo "$age岁"
??
echo "${age}岁"
18岁
复制代码

默认情况下,echo在每次调用后会添加一个换行符,同时也可以使用-n忽略行号符,例如:

echo "male";echo "female"
male
female
echo -n "male";echo "female"
malefemale
复制代码

装逼模式,彩色输出

//输出加粗红色字体
echo -e "\033[01;31m颜色字体\033[0m"
颜色字体

//  /03[4m   下划线   
// /033[5m   闪烁 
复制代码

上面输出格式中01表示加粗,31表示是红色,后面\033[0m表示恢复所有的属性为原来的默认值

字体色号 颜色 背景色号 颜色
30 黑色 40 黑色
31 红色 41 红色
32 绿色 42 绿色
33 黄色 43 黄色
34 蓝色 44 蓝色
35 紫色 45 紫色
36 深绿色 46 深绿色
37 白色 47 白色

cd 遍历目录

cd 命令可接受相对路径和绝对路径

ls 显示当前目录的文件和文件夹

ls命令支持定义过滤器,通过过滤器决定输出哪些文件或目录。

可以使用简单匹配字符:

  1. ?代表一个字符
  2. *代表一个星号
  3. []代表元字符或者[a-c]代表范围
  4. [!a]使用感叹号将不需要的内容排除在外

在使用参数过程中,可以组合参数使用,例如:

ls  -aF
./				.putty/
../				.sogouinput/
.CFUserTextEncoding		.ssh/
.DS_Store			.templateengine/
.IdentityService/		.viminfo
.ServiceHub/			.yarnrc

复制代码
参数 作用
-F 区分文件与文件夹,文件夹后面会带/斜杠
-a 显示隐藏文件
-R 递归显示
-l 显示文件的相关信息

touch 创建文件

例如:

touch data.txt
复制代码

cp 复制文件

格式:cp [file1] [file2]

格式:cp [file1] [file2] directory 该命令必须在directory存在的情况下使用

注意当使用-R拷贝文件夹时,如果file2文件夹已经存在会在file2在创建file1的递归文件

当执行复制时,如果file2文件已经存在,则会覆盖file2的文件

参数 含义
-i 如果file2存在时,询问是否覆盖
-R 递归复制整个目录
-f 如果对象已经存在则先删除

mv 移动或重命名

格式: mv [file1] [file2]

格式:mv [file1] [file2] directory

参数 含义
-i 如果file2存在时,询问是否覆盖
-R 递归复制整个目录

rm 删除文件

格式: rm [file]

格式: rm -r directory

支持使用通配符成组的删除文件

参数 含义
-i 询问是否删除
-f 强制删除
-r -R 直接删除普通文件,如果是路径就会一次删除下一级路径和文件

mkdir 创建目录 rmdir 删除目录

mkdir

格式: mkdir directory

参数 含义
-p 创建路径中缺失的父目录

rmdir

格式: rmdir directory

该命令很少使用,因为该命令只能删除空目录

参数 含义
-p 创建路径中缺失的父目录

file 查看文件类型

格式: file [file]

cat 查看文件内容

格式: cat [file]

参数 含义
-n 给所有的行加上行号
-n 给只有文件的行加上行号

find 文件查找

格式: find base_path

列出当前目录及子目录下的所有文件和文件夹

根据文件名或正则表达式匹配

格式:find base_path -name

例如:

//查找当前目录下以“.txt”结尾的文件
find . -name "*.txt"
//查找当前目录下以“.txt”或“.pdf”结尾并忽略大小写的文件,“\(\)”是指将括号内的内容视为一个整体
find . \( -iname "*.txt" -o -iname "*.pdf" \)
复制代码

根据文件路径匹配

将文件路径作为一个整体进行匹配

格式: find base_path -path

例如:

find . -path "*txt"
复制代码

使用否定参数

例如:

//查找当前目录下不以“.txt”结尾的文件
find . ! -name "*.txt"
复制代码

基于目录的深度搜索

格式:

  1. -maxdepth num最大深度num
  2. -mindepth num最小深度num

例如:

//查找当前目录及子目录下以“.txt”结尾的文件
find . -maxdepth 2 -name "*.txt"
复制代码

基于文件类型搜索

-type对文件类型进行过滤

-type f 普通文件 -type d 目录

基于文件大小搜索

例如:

//搜索大于2k的文件
find . -type f -size +2k
复制代码

删除匹配的文件

例如:

//删除大于2k的文件
find . -type f -size +2k -delete
复制代码

跳过特定的目录

例如:

find . \( -name ".git" -prune \) -o \( -type f -print \)
复制代码

gzip 压缩文件 gunzip 解压文件

gzip

格式: gzip [file]

gunzip

格式: gunzip [file]

重定向与管道

简介

重定向与管道的操作过程如图:

基本命令行程序都能在屏幕上显示输出结果,称之为标准输出,文件的描述符数值为1。同时我们也可以利用标准输出重定向保存为文件,将文件内容指定为命令的输入

输出重定向

格式: ls > [file]

>操作会将原有的内容覆盖,如果我们需要添加内容则使用>>

输入重定向

格式: command < [file]

文件描述符

标准I/OW文件描述符类型如下:

I/O 描述符
输入 0
输出 1
错误 2

使用方法:

//将错误输出到stderr.tet 正常输出到stdout.txt
ls + 2>stderr.txt 1>stdout.txt
复制代码

管道

通常通过组合指令、连续使用指令的方法执行多个指令,此时就可以使用|字符连接两个指令。这就是管道,表示前一命令的结果值成为下一个命令的输入。

格式: ls -l | less

高级语法

grep

基本使用

grep命令是UNIX中用于搜索的大师级工具,能够接受正则表达式和通配符。

格式: grep [格式] [文件]

grep可以多个文件进行搜索,例如: grep [格式] [文件] [文件] [文件] ...

选项 含义
-E 使用扩展正则表达式
-P 使用Perl正则表达式
-o 只输出文件中匹配到文本的部分
-v 输出匹配行之外的所有行
-c 统计文件或者文本中匹配的行数
-l 搜索多个文件,并找出匹配文本位于哪个文件中
-R 递归搜索文件
-i 忽略大小写
-e 匹配多个样式
-A 输出匹配结果之后的几行
-B 输出匹配结果之前的几行
-C 输出匹配结果之前和之后的几行

例如:

cat data.txt
112233444
a1a1a1a1a1
bring1
pipei
44454321

grep -E "^1" data.txt
112233444

grep -E -o "^b" data.txt
b

grep -v "^b" data.txt
112233444
a1a1a1a1a1
pipei
44454321
aaa12122


grep -e "^b" -e "4$" data.txt
112233444
bring1

grep -E "^b.+1$" data.txt -A 1
bring1
pipei

grep -E "^b.+1$" data.txt -B 1
a1a1a1a1a1
bring1

grep -E -c "4$" data.txt
1

//在递归搜索所有的`.c`和`.cpp`文件
grep "title" dir2 -R --include *.{c,cpp}
//在搜索中排除所有的readme文件
grep "title" dir -R --excluds "readme"

复制代码

grep中的静默输出

在某些情况下,只需要知道一个文件是否包含指定的文本,因此通过设置grep中的-q执行一个可以返回真假的条件测试。在静默模式中,grep命令不会向标准输入打印任何输出,仅仅是运行命令,根据命令执行成功与否返回退出的状态。

例如:

grep -q "test" file
if [ $? -eq 0 ];then
echo "包含test"
fi
复制代码

egrep

egrep是grep的扩展,可以使用其他正则表达式的元字符集,相当于grep -E模式。

持续更新.....

猜你喜欢

转载自juejin.im/post/5bafb706e51d450e8f5fb7de
今日推荐