Shell学习心得
学习完shell之后,发现还挺有意思的,但是还需要多加练习才行,比如那shell脚本,要多练,多记,多背,脚本执行起来挺有意思,但是背后还需要自己去把脚本内容一点点的写好才行,所以shell要多练习编写脚本,熟练shell的命令。
Shell介绍
Shell是一个命令行解释器,它接收应用程序、用户命令,然后调用操作系统内核;Shell还是一个功能相当强大的编程语言,易编写,易调试,灵活性强。
Shell使用场景
1.读取文件内容
2.操作字符串
3.统计目录下文件/目录个数
4.生成指定范围内的随机数
5.生成指定长度的随机字符串
6.清理磁盘中空文件夹
总结Shell
编程语言分类
(1)编译型语言:
程序在执行之前需要个专门的编译过程,把程序编译成为机器语言文件,运行时不需要重新翻译,直接使用编译的结果就行了。程序执行效率高,依养编译器,跨平台性差些。如C、C++
(2)解释型语言:
程序不需要编译,程序在运行时由解释器翻译成机器语言,每执行一次都要翻译一次。因此效率比较低。比如Python/javaScript/Shell等都是解释型语言。
Shell解析器
Linux提供的Shell解析器有:
/bin/sh 是bash的一个快捷方式
/bin/bash bash是大多数Linux默认的shell,包含的功能几乎可以涵盖shell所有的功能
/sbin/nologin 表示非交互,不能登录操作系统
/bin/dash 小巧,高效,功能相比少一些
/bin/tcsh 具有C语言风格的一种shell,具有许多特性,但是也有一些缺陷
/bin/csh 是csh的增强版本,完全兼容csh
Shell脚本入门
1.脚本格式
脚本以#!/bin/bash或者#!/bin/env bash开头(指定解析器)
2.脚本的常用执行方式
第一种:采用bash或sh+脚本的相对路径或绝对路径(不用赋予脚本+x权限)
sh+脚本的相对路径
sh+脚本的绝对路径
bash+脚本的相对路径
bash+脚本的绝对路径
第二种:采用输入脚本的绝对路径或相对路径执行脚本(必须具有可执行权限+x,推荐采用这种方式)
(a)首先要赋予helloworld.sh 脚本的+x权限
(b)执行脚本(相对路径,绝对路径)
注意:第一种执行方法,本质是bash解析器帮你执行脚本,所以脚本本身不需要执行权限。第二种执行方法,本质是脚本需要自己执行,所以需要执行权限。
第二个Shell脚本:多命令处理
(1)需求:
在/home/jinghang/目录下创建一个banzhang.txt,在banzhang.txt文件中增加“I love you”,
执行完毕后打印“报告班长,任务在2019年12月14日 xx:xx:xx 执行完毕”。
(2)案例实操:
[jinghang@hadoop101 datas]$ touch batch.sh
[jinghang@hadoop101 datas]$ vi batch.sh
在batch.sh中输入如下内容
#!/bin/bash
cd /home/jinghang
touch cls.txt
echo “I love you” >>cls.txt
(3)查看脚本的执行流程(一般使用这个命令来查看脚本执行的步骤,错误)
[jinghang@hadoop101 datas]$ bash -x batch.sh
(4)查看脚本的语法(一般使用这个命令来查看脚本语法错误)
[jinghang@hadoop101 datas]$ bash -n batch.sh
Shell中的变量
变量是用来临时保存数据的,该数据是可以变化的数据
什么时候需要定义变量?
1.如果某个内容需要多次使用,并且在代码中重复出现,那么可以使用变量代表该内容,
这样在修改内容的时候,仅仅需要修改变量的值。
2.在代码运作的过程中,可能会把某些命令的执行结果保存起来,后续代码需要使用这些结果,
就可以直接使用这个变量。
系统变量
- 常用系统变量
H O M E 、 HOME、 HOME、PWD、 S H E L L 、 SHELL、 SHELL、USER等
2.案例实操
(1)查看系统变量的值
[jinghang@hadoop101 datas]$ echo
H
O
M
E
/
h
o
m
e
/
j
i
n
g
h
a
n
g
(
2
)
显
示
当
前
S
h
e
l
l
中
所
有
变
量
:
s
e
t
[
j
i
n
g
h
a
n
g
@
h
a
d
o
o
p
101
d
a
t
a
s
]
HOME /home/jinghang (2)显示当前Shell中所有变量:set [jinghang@hadoop101 datas]
HOME/home/jinghang(2)显示当前Shell中所有变量:set[jinghang@hadoop101datas] set
BASH=/bin/bash
BASH_ALIASES=()
BASH_ARGC=()
BASH_ARGV=()
自定义变量
1.基本语法
(1)定义变量:变量名=变量值
(2)撤销变量:unset 变量名
(3)声明静态变量:readonly变量,注意:不能unset
2.变量定义规则
(1)变量名称可以由字母、数字和下划线组成,但是不能以数字开头,环境变量名建议大写。
(2)等号两侧不能有空格
(3)在bash中,变量默认类型都是字符串类型,无法直接进行数值运算。
(4)变量的值如果有空格,需要使用双引号或单引号括起来。
3.案例实操
(1)定义变量A
[jinghang@hadoop101 datas]$ A=5
[jinghang@hadoop101 datas]$ echo
A
5
(
2
)
给
变
量
A
重
新
赋
值
[
j
i
n
g
h
a
n
g
@
h
a
d
o
o
p
101
d
a
t
a
s
]
A 5 (2)给变量A重新赋值 [jinghang@hadoop101 datas]
A5(2)给变量A重新赋值[jinghang@hadoop101datas] A=8
[jinghang@hadoop101 datas]$ echo
A
8
(
3
)
撤
销
变
量
A
[
j
i
n
g
h
a
n
g
@
h
a
d
o
o
p
101
d
a
t
a
s
]
A 8 (3)撤销变量A [jinghang@hadoop101 datas]
A8(3)撤销变量A[jinghang@hadoop101datas] unset A
[jinghang@hadoop101 datas]$ echo
A
(
4
)
声
明
静
态
的
变
量
B
=
2
,
不
能
u
n
s
e
t
[
j
i
n
g
h
a
n
g
@
h
a
d
o
o
p
101
d
a
t
a
s
]
A (4)声明静态的变量B=2,不能unset [jinghang@hadoop101 datas]
A(4)声明静态的变量B=2,不能unset[jinghang@hadoop101datas] readonly B=2
[jinghang@hadoop101 datas]$ echo
B
2
[
j
i
n
g
h
a
n
g
@
h
a
d
o
o
p
101
d
a
t
a
s
]
B 2 [jinghang@hadoop101 datas]
B2[jinghang@hadoop101datas] B=9
-bash: B: readonly variable
(5)在bash中,变量默认类型都是字符串类型,无法直接进行数值运算
[jinghang@hadoop101 ~]$ C=1+2
[jinghang@hadoop101 ~]$ echo
C
1
+
2
(
6
)
变
量
的
值
如
果
有
空
格
,
需
要
使
用
双
引
号
或
单
引
号
括
起
来
[
j
i
n
g
h
a
n
g
@
h
a
d
o
o
p
101
]
C 1+2 (6)变量的值如果有空格,需要使用双引号或单引号括起来 [jinghang@hadoop101 ~]
C1+2(6)变量的值如果有空格,需要使用双引号或单引号括起来[jinghang@hadoop101 ] D=I love banzhang
-bash: world: command not found
[jinghang@hadoop101 ~]$ D=“I love banzhang”
[jinghang@hadoop101 ~]$ echo
A
I
l
o
v
e
b
a
n
z
h
a
n
g
(
7
)
可
把
变
量
提
升
为
全
局
环
境
变
量
,
可
供
其
他
S
h
e
l
l
程
序
使
用
e
x
p
o
r
t
变
量
名
[
j
i
n
g
h
a
n
g
@
h
a
d
o
o
p
101
d
a
t
a
s
]
A I love banzhang (7)可把变量提升为全局环境变量,可供其他Shell程序使用 export 变量名 [jinghang@hadoop101 datas]
AIlovebanzhang(7)可把变量提升为全局环境变量,可供其他Shell程序使用export变量名[jinghang@hadoop101datas] vim helloworld.sh
在helloworld.sh文件中增加echo $B
#!/bin/bash
echo “helloworld”
echo $B
[jinghang@hadoop101 datas]$ ./helloworld.sh
Helloworld
发现并没有打印输出变量B的值。
[jinghang@hadoop101 datas]$ export B
[jinghang@hadoop101 datas]$ ./helloworld.sh
helloworld
2
特殊变量:$n
1.基本语法
$n (功能描述:n为数字,$0代表该脚本名称,$1-
9
代
表
第
一
到
第
九
个
参
数
,
十
以
上
的
参
数
,
十
以
上
的
参
数
需
要
用
大
括
号
包
含
,
如
9代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如
9代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如{10})
特殊变量:$#
1.基本语法
$# (功能描述:获取所有输入参数个数,常用于循环)。
特殊变量:
∗
、
*、
∗、@
1.基本语法
∗
(
功
能
描
述
:
这
个
变
量
代
表
命
令
行
中
所
有
的
参
数
,
* (功能描述:这个变量代表命令行中所有的参数,
∗(功能描述:这个变量代表命令行中所有的参数,*把所有的参数看成一个整体)
@
(
功
能
描
述
:
这
个
变
量
也
代
表
命
令
行
中
所
有
的
参
数
,
不
过
@ (功能描述:这个变量也代表命令行中所有的参数,不过
@(功能描述:这个变量也代表命令行中所有的参数,不过@把每个参数区分对待)
特殊变量:$?
1.基本语法
$? (功能描述:最后一次执行的命令的返回状态。如果这个变量的值为0,证明上一个命令正确执行;如果这个变量的值为非0(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了。)
Shell 中的数组
Shell 数组用括号来表示,元素用"空格"符号分割开,语法格式如下:
方式2: arr=(value1 value2 value3) (这种方式带值)
注意:往数组里添加值,数组的长度自动增长
运算符
1.基本语法
(1)“
(
(
运
算
式
)
)
”
或
“
((运算式))”或“
((运算式))”或“[运算式]” + , - , *, /, % 加,减,乘,除,取余
(2)expr + , - , *, /, % 加,减,乘,除,取余
注意:expr运算符间要有空格
条件判断
1.基本语法
[ condition ](注意condition前后要有空格)
注意:条件非空即为true,[ jinghang ]返回true,[] 返回false。
2. 常用判断条件
(1)两个整数之间比较
= 字符串比较
-lt 小于(less than) -le 小于等于(less equal)
-eq 等于(equal) -gt 大于(greater than)
-ge 大于等于(greater equal) -ne 不等于(Not equal)
(2)按照文件权限进行判断
-r 有读的权限(read) -w 有写的权限(write)
-x 有执行的权限(execute)
(3)按照文件类型进行判断
-f 文件存在并且是一个常规的文件(file)
-e 文件存在(existence) -d 文件存在并是一个目录(directory)
流程控制(重点)
if 判断
1.基本语法
if [ 条件判断式 ];then
程序
fi
或者
if [ 条件判断式 ]
then
程序
elif [ 条件判断式 ]
then
程序
else
程序
fi
注意事项:
(1)[ 条件判断式 ],中括号和条件判断式之间必须有空格
(2)if后要有空格
case 语句
1.基本语法
case $变量名 in
“值1”)
如果变量的值等于值1,则执行程序1
;;
“值2”)
如果变量的值等于值2,则执行程序2
;;
…省略其他分支…
*)
如果变量的值都不是以上的值,则执行此程序
;;
esac
注意事项:
1)case行尾必须为单词“in”,每一个模式匹配必须以右括号“)”结束。
2)双分号“;;”表示命令序列结束,相当于java中的break。
3)最后的“”表示默认模式,相当于java中的default。
for 循环
1.基本语法1
for (( 初始值;循环控制条件;变量变化 ))
do
程序
done
2. 基本语法2
for 变量 in 值1 值2 值3…
do
程序
done
比较 ∗ 和 *和 ∗和@区别
(a)
∗
和
*和
∗和@都表示传递给函数或脚本的所有参数,不被双引号“”包含时,都以$1
2
…
2 …
2…n的形式输出所有参数
(b)当它们被双引号“”包含时,“$*”会将所有的参数作为一个整体,以“$1
2
…
2 …
2…n”的形式输出所有参数;“$@”会将各个参数分开,以“$1” “
2
”
…
”
2”…”
2”…”n”的形式输出所有参数。
while 循环
1.基本语法
while [ 条件判断式 ]
do
程序
done
read读取控制台输入
1.基本语法
read(选项)(参数)
选项:
-p:指定读取值时的提示符;
-t:指定读取值时等待的时间(秒)。
参数
变量:指定读取值的变量名
函数
系统函数
1.basename基本语法
basename [string / pathname] [suffix] (功能描述:basename命令会删掉所有的前缀包括最后一个(‘/’)字符,然后将字符串显示出来。
选项:
suffix为后缀,如果suffix被指定了,basename会将pathname或string中的suffix去掉。
dirname基本语法
dirname 文件绝对路径 (功能描述:从给定的包含绝对路径的文件名中去除文件名(非目录的部分),然后返回剩下的路径(目录的部分))
自定义函数
1.基本语法
[ function ] funname[()]
{
Action;
[return int;]
}
funname
2.经验技巧
(1)必须在调用函数地方之前,先声明函数,shell脚本是逐行运行。不会像其它语言一样先编译。
(2)函数返回值,只能通过$?系统变量获得,可以显示加:return返回,如果不加,将以最后一条命令运行结果,作为返回值。return后跟数值n(0-255)
Shell工具(文本处理)
1.cut
cut的工作就是“剪”,具体的说就是在文件中负责剪切数据用的。cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段输出。
1.基本用法
cut [选项参数] filename
说明:默认分隔符是制表符
2.选项参数说明
选项参数 | 功能 |
---|---|
-f | 列号,提取第几列 |
-d | 分隔符,按照指定分隔符分割列 |
-c | 指定具体的字符 |
2 .sed
sed是一种流编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。
1.基本用法
sed [选项参数] ‘command’ filename
2.选项参数说明
选项参数 | 功能 |
---|---|
-e | 直接在指令列模式上进行sed的动作编辑(一次执行多个操作时) |
-i | 直接编辑文件 |
3.命令功能描述
命令 | 功能描述 |
---|---|
a | 新增,a的后面可以接字串,在下一行出现 |
d | 删除 |
s | 查找并替换 |
3 awk
一个强大的文本分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理。
1.基本用法
awk [选项参数] ‘pattern1{action1} pattern2{action2}…’ filename
pattern:表示AWK在数据中查找的内容,就是匹配模式
action:在找到匹配内容时所执行的一系列命令
2.选项参数说明
表1-55
选项参数 | 功能 |
---|---|
-F | 指定输入文件折分隔符 |
-v | 赋值一个用户定义变量 |
3.awk的内置变量
变量 | 说明 |
---|---|
FILENAME | 文件名 |
NR | 已读的记录数 |
NF | 浏览记录的域的个数(切割后,列的个数) |
4 sort
sort命令是在Linux里非常有用,它将文件进行排序,并将排序结果标准输出。
1.基本语法
sort(选项)(参数)
选项 | 说明 |
---|---|
-n | 依照数值的大小排序 |
-r | 以相反的顺序来排序 |
-t | 设置排序时所用的分隔字符 |
-k | 指定需要排序的列 |
参数:指定待排序的文件列表
Shell面试题
1.每个脚本开始的 #!/bin/sh 或 #!/bin/bash 表示什么意思 ?
这一行说明要使用的 shell。#!/bin/bash 表示脚本使用 /bin/bash
2.晚上11点到早上8点之间每两个小时查看一次系统日期与时间,写出具体配置命令
echo 1 23,1-8/2 * * * root /tmp/walldate.sh >> /etc/crontab
3.编写个shell脚本将当前目录下大于10K的文件转移到/tmp目录下
#!/bin/bash
fileinfo=(
(
d
u
.
/
∗
)
)
l
e
n
g
t
h
=
(du ./*)) length=
(du./∗))length={#fileinfo[@]}
for((i=0;i<
l
e
n
g
t
h
;
i
=
length;i=
length;i=(( i+2 ))));do
if [ KaTeX parse error: Expected '}', got 'EOF' at end of input: {fileinfo[i]} -le 10 ];then
mv KaTeX parse error: Expected '}', got 'EOF' at end of input: {fileinfo[(( i+1 ))]} /tmp
fi
done
4.在11月份内,每天的早上6点到12点中,每隔2小时执行一次/usr/bin/httpd.sh 怎么实现
echo “1 6-12/2 * * * root /usr/bin/httpd.sh >> /etc/crontab”
5.在shell里如何新建一个文件?
touch ~/newfile.txt
6.linux下面的sed和awk的编写
1) 如何显示文本file.txt中第二大列大于56789的行?
awk -F “,” ‘{if($2>56789){print $0}}’ file.txt
2) 显示file.txt的1,3,5,7,10,15行?
sed -n “1p;3p;5p;7p;10p;15p” file.txt
awk ‘NR1||NR3||NR==5||…||NR=15{print $0}’ file.txt
3) 将file.txt的制表符,即tab,全部替换成"|"
sed -i “s#\t#|#g” file.txt
7.把当前目录(包含子目录)下所有后缀为“.sh”的文件后缀变更为“.shell”
#!/bin/bash
str=find ./ -name \*.sh
for i in $str
do
mv $i ${i%sh}shell
done
8.编写shell实现自动删除50个账号功能,账号名为stud1至stud50
#!/bin/bash
for((i=1;i<=50;i++));do
userdel stud$i
done
9.请用Iptables写出只允许10.1.8.179 访问本服务器的22端口。
/sbin/iptables -A input -p tcp -dport 22 -s 10.1.8.179 -j ACCEPT
/sbin/iptables -A input -p udp -dport 22 -s 10.1.8.179 -j ACCEPT
/sbin/iptables -P input -j DROP
10.在shell中变量的赋值有四种方法,其中,采用name=12的方法称( A ) 。
A直接赋值 B使用read命令
C使用命令行参数 D使用命令的输出
11.有文件file1
- 查询file1里面空行的所在行号
grep -n ^$ file1 - 查询file1以abc结尾的行
grep abc$ file1 - 打印出file1文件第1到第三行
head -n3 file1
sed “3q” file1
sed -n “1,3p” file1
12.假设有一个脚本scan.sh,里面有1000行代码,并在vim模式下面,请按照如下要求写入对应的指令
1) 将shutdown字符串全部替换成reboot
:%s/shutdown/reboot/g
2) 清空所有字符
:%d
3) 不保存退出
q!
13.1到10数字相加,写出shell脚本
#!/bin/bash
j=0
for((i=1;i<=10;i++));do
j=$[j+i ]
done
echo $j
14.常见shell有哪些?缺省的是哪个?
/bin/sh /bin/bash /bin/ash /bin/bsh /bin/csh /bin/tcsh /sbin/nologin
15.Shell循环语句有哪些?
for while until
for)
for i in
(
l
s
)
;
d
o
e
c
h
o
i
t
e
m
:
(ls);do echo item:
(ls);doechoitem:i
done
while)
#!/bin/bash
COUNTER=0
while [ $COUNTER -lt 10 ]; do
echo The counter is $COUNTER
let COUNTER=COUNTER+1
done
until)#!/bin/bash
COUNTER=20
until [ $COUNTER -lt 10 ]; do
echo COUNTER $COUNTER
let COUNTER-=1
done
16.找出系统内大于50k,小于100k的文件,并删除它们。
#!/bin/bash
file=find / -size +50k -size -100k
for i in $file;do
rm -rf $i
done
17.脚本(如:目录dir1、dir2、dir3下分别有file1、file2、file2,请使用脚本将文件改为dir1_file1、dir2_file2、dir3_file3)
#!/bin/bash
file=ls dir[123]/file[123]
for i in $file;do
mv $i KaTeX parse error: Expected '}', got 'EOF' at end of input: {i%/*}/{i%%/}_${i##/}
done
18.将A 、B、C目录下的文件A1、A2、A3文件,改名为AA1、AA2、AA3.使用shell脚本实现。
#!/bin/bash
file=ls [ABC]/A[123]
for i in $file;do
mv $i KaTeX parse error: Expected '}', got 'EOF' at end of input: {i%/*}/A{i#*/}
done
19.Shell脚本是什么、它是必需的吗?
答:一个Shell脚本是一个文本文件,包含一个或多个命令。作为系统管理员,我们经常需要使用多个命令来完成一项任务,我们可以添加这些所有命令在一个文本文件(Shell脚本)来完成这些日常工作任务。
20.什么是默认登录shell,如何改变指定用户的登录shell
答:在Linux操作系统,“/bin/bash”是默认登录shell,是在创建用户时分配的。使用chsh命令可以改变默认的shell。示例如下所示:
chsh <用户名> -s <新shell># chsh linuxtechi -s /bin/sh
21.可以在shell脚本中使用哪些类型的变量?
答:在shell脚本,我们可以使用两种类型的变量:
系统定义变量
用户定义变量
系统变量是由系统系统自己创建的。这些变量通常由大写字母组成,可以通过“set”命令查看。
用户变量由系统用户来生成和定义,变量的值可以通过命令“echo $<变量名>”查看。
22.shell脚本中“$?”标记的用途是什么?
答:在写一个shell脚本时,如果你想要检查前一命令是否执行成功,在if条件中使用“$?”可以来检查前一命令的结束状态。简单的例子如下:
root@localhost:~# ls /usr/bin/shar/usr/bin/sharroot@localhost:~# echo $?0
如果结束状态是0,说明前一个命令执行成功。
root@localhost:~# ls /usr/bin/sharels: cannot access /usr/bin/share: No such file or directoryroot@localhost:~# echo $?2
如果结束状态不是0,说明命令执行失败。
23.如何使脚本可执行 ?
答:使用chmod命令来使脚本可执行。例子如下:
chmod a+x myscript.sh