Shell学习笔记

Shell 学习

Shell 是一个用C语言编写的程序,它是用户使用Linux的桥梁。

Shell既是一种命令语言,又是一种程序设计语言。

Shell也是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。

Shell 脚本(shell script),是一种为shell编写的脚本程序。业界所说的shell通常都是指shell脚本。

在一般情况下,人们并不区分 Bourne Shell 和 Bourne Again Shell,所以,像 #!/bin/sh,它同样也可以改为**#!/bin/bash**。#!告诉系统其后路径所指定的程序即是解释此脚本文件的Shell程序。

变量

your_name="jacky"

  • 首个字符必须为字母(a-z,A-Z)。
  • 中间不能有空格,可以使用下划线(_)。
  • 不能使用标点符号。
  • 不能使用bash里的关键字(可用help命令查看保留关键字)。

使用变量

使用一个定义过的变量,只要在变量名前面加美元符号$即可

1
2
3
your_name="hello world"
echo $your_name
echo ${your_name}

字符串

字符串是shell编程中最常用最有用的数据类型

单引号

单引号字符串的限制:

  • 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的
  • 单引号字串中不能出现单引号(对单引号使用转义符后也不行)

双引号

双引号的优点:

  • 双引号里可以有变量
  • 双引号里可以出现转义字符

拼接字符

1
2
3
your_name="jacky"
greeting="hello, "$your_name" !"
greeting="hello, ${your_name} !"

获取字符串长度

${#string}

提取子字符串

${string:1:4}

查找子字符串

???

数组

bash支持一维数组(不支持多维数组),并且没有限定数组的大小。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 定义
array_name=(value0 value1 value2 ...)
array_name=(
value0
value1
value2
)
array_name[0]=value0

# 读取
valuen=${array_name[n]} #第n个
${array_name[@]} 读取全部

# 获取长度
${#array_name[@]}
${#array_name[*]}
${#array_name[n]} # 取得数组单个元素的长度

传递参数

我们可以在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:**$n**

1
2
3
4
5
6
7
$# # 参数个数
$* # 所有参数用
$@ # 所有参数分割表示
$$ # 当前进程号
$! # 后台运行的最后一个进程号
$- # 显示Shell使用的当前选项
$? # 退出状态,正常为0

运算符

  • 算数运算符
  • 关系运算符
  • 布尔运算符
  • 字符串运算符
  • 文件测试运算符

算数运算符

expr 是一款表达式计算工具,使用它能完成表达式的求值操作。

  • 表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2
  • 完整的表达式要被 ` ` 包含
  • + - * / % = == !==, 其中条件表达式要放进[]中:[$a == $b] #mac系统用(($a == $b))

关系运算符

关系运算符只支持数字,不支持字符串,除非字符串的值是数字。

1
2
3
4
5
6
7
a=10, b=20
-eq # 相等 [$a -eq $b] false
-ne # 不相等 [$a -ne $b] true
-gt # 大于 [$a -gt $b] false
-lt # 小于 [$a -lt $b] true
-ge # 大于等于 [$a -ge $b] false
-le # 小于等于 [$a -le $b] true

布尔运算符

! -o -a 非,或(一个true则true),与(两个true则true)

逻辑运算符

1
2
3
a=10, b=20
&& [[$a -lt 100 && $b -gt 100]] #false
|| [[$a -lt 100 || $b -gt 100]] #true

字符运算符

1
2
3
4
5
6
a="abc", b="efg"
= [$a = $b] #false
!= [$a != $b] #true
-z [-z $a] #false, 检查是否长度为0
-n [-n $b] #true, 检查长度不为0
str [$a] #true,检查字符串不为空

文件检查符

1
2
3
4
5
6
7
-b #是否块设备文件
-c #字符设备文件
-d #是否目录
-f #是否普通文件
-g -k -p -u #SGID 粘着位(Sticky Bit) 有名管道 SUID
-r -w -x #可读 可写 可执行
-s -e #空 存在

echo命令

执行:echo string

  1. 普通字符可省略引号
  2. \转义字符
  3. read name; echo $name read 命令从标准输入中读取一行,并把输入行的每个字段的值指定给 shell 变量
  4. \n换行
  5. 显示不换行-e \c
  6. 重定向>
  7. 单引号不转义echo '$name\"' 输出$name\"
  8. 显示执行结果``

printf命令

printf 命令模仿 C 程序库(library)里的 printf() 程序。

标准所定义,因此使用printf的脚本比使用echo移植性好。

printf 使用引用文本或空格分隔的参数,外面可以在printf中使用格式化字符串,还可以制定字符串的宽度、左右对齐方式等。默认printf不会像 echo 自动添加换行符,我们可以手动添加 \n。

printf format-string [arguments...]

格式替代符

  • %s 宽度,%-10s宽度为10个字符(-表示左对齐,没有则表示右对齐)
  • %c
  • %d
  • %f 指格式化为小数,%-4.2f 表示4位数其中2位小数,左对齐

转义序列

1
2
3
4
5
6
7
\a
\b # 后退
\c # 不显示。。。??
\f \n \r \t \v # 换页 换行 回车 水平制表符 垂直制表符
\\ # 反斜杠字符
\ddd # 表示1到3位数八进制值的字符。仅在格式字符串中有效
\0ddd # 表示1到3位的八进制值字符

test命令

Shell中的 test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。

流程控制

if-else

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
if [condition]
then
command1
...
fi

# ----- 单行 -----
if [condition]; then command; fi

# ----- if else -----
if [condition]
then
command1
...
else
command2
...
fi

# ----- if else-if else -----
if [condition]
then
command1
elif [condition2]
command2
else
command3
fi

for 循环

1
2
3
4
5
6
7
for var in item1 item2 ... itemN
do
command1 $var
command2 $var
...
commandN $var
done

while 循环

1
2
3
4
while condition
do
command1
done

until 循环

until循环执行一系列命令直至条件为真时停止。

until循环与while循环在处理方式上刚好相反。

一般while循环优于until循环,但在某些时候—也只是极少数情况下,until循环更加有用。

条件可为任意测试条件,测试发生在循环末尾,因此循环至少执行一次

1
2
3
4
until condition
do
command
done

case

类似JS switch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
case var in
mode1)
command
...
;;
mode2)
command
...
;;
*)
command
...
;;
esac

跳出循环

break continue

esac

case语法需要一个esac作为结束标记,每一个分支用右圆括号,两个分号表示break

函数

1
2
3
4
5
[function] funcName [()] # 可以用function funcName(),也可以 funcName()
{
action;
[retrun int] #可以返回0-255,或用最后一条结果返回
}

函数返回值在调用该函数后通过 $? 来获得。

所有函数在使用前必须定义。

参数

1
$n ${n>=10} # 第n个参数$# # 参数个数$* # 所有参数用$@ # 所有参数分割表示$$ # 当前进程号$! # 后台运行的最后一个进程号$- # 显示Shell使用的当前选项$? # 退出状态,正常为0

输入/输出重定向

一个命令通常从标准输入(一般是终端)读取,处理后输出到标准输出(一般是终端)。

1
command > filecommand < file # 输入重定向到filecommand >> file # 追加重定向输出n > file # 将文件描述符为 n 的文件重定向到 file。n >> file	# 0 通常是标准输入(STDIN),	# 1 是标准输出(STDOUT),	# 2 是标准错误输出(STDERR)n >& m # 将输出文件 m 和 n 合并n <& m # 将输入文件 m 和 n 合并<< tag # 将开始标记 tag 和结束标记 tag 之间的内容作为输入。

输入重定向

command < file1 > file2

如果想输出错误(stderr)到文件 command 2 > file # 2表示标准错误文件(stderr)

如果希望将 stdout 和 stderr 合并后重定向到 file command > file > 2 &> 1

Here Document

Here Document 是 Shell 中的一种特殊的重定向方式,用来将输入重定向到一个交互式 Shell 脚本或程序。

1
wc -l << EOF	文本文本	文本文本EOF

/dev/null

如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null

如果希望屏蔽 stdout 和 stderr command > /dev/null 2>&1

文件包含

. filename 或者 source filename

1
# test1.shurl="https://www.bing.com"# test2.sh. ./test1.sh #或者 source ./test1.shecho "Welcome to visit $url"