Shell:英文翻译为“壳”。对,没错,它就是个“壳”,就像我们常见的鸡蛋一样,shell就是那层“壳”。
在我们的linux操作系统中,有内核和具体的硬件,内核(kernel)将所有硬件的实现隐藏起来,并由其(kernel)控制具体的硬件工作。但是,内核在整个系统中极其重要,我们不希望被随意的进行操作,于是我们就在内核上包裹一层“壳”,用户通过这层“壳”来与内核通信,并最终控制具体的硬件。
shell的功能只是提供用户操作系统的一个接口,应用程序通过shell来和kernel进行交互控制硬件,实现具体的功能。
而shell本身也是个应用程序,只是它被用来与内核(kernel)打交道。
shell的版本有很多,例如Bourne Shell(sh),C shell,kshell、zshell等等,在linux我们常用的就是bash(Bourne Again Shell),它是Bourne Shell(sh)的增强版。
shell脚本是利用shell的功能所写的一个程序,这个程序是用纯文本文件,将一些shell的语法与指令写在里面,搭配正规表示法、管线命令与数据流重导向等功能,已达到我们想要的处理母的。
shell脚本有点类似于我们在windows下的批处理文件(.bat).
shell脚本是一种过程式的编程,解释运行,依赖于外部程序文件运行。它不同于其它编译型语言(c、c++,java等),它的源代码在运行时启动解释器,由解释器边解释变运行,而编译型语言是源代码经过编译器编译后的二进制可执行文件。
运行shell脚本有3种方式:
(1)给脚本添加可执行权限,直接运行文件
例如:chmod +x /PATH/TO/SCRIPT_FILE
(2)直接调用命令解释器执行程序
例如:bash /PATH/TO/SCRIPT_FILE
(3)使用source运行
source又被称为“点”命令,通常用于重新执行刚修改的初始化文件,使之立即生效。
source命令影响shell进程本身,在脚本执行过程中,无子进程的创建和消亡
注意:
①脚本中的空白行都被忽略
②脚本中,所有以#开头的行,都会被视作注释行而被忽略,即为注释行
③shell脚本的运行是通过运行一个子shell进程实现的。
shell进程中定义的命令别名或变量等,仅在当前shell进程中有效,无法在其他shell进程中发挥作用,如果我们想要这些变量或命令别名在其他shell进程中同样发挥作用,则我们需要修改bash的配置文件。
配置文件分为两类:
(1)profile类:为交互式登录的shell进程提供配置
全局:对所有用户都生效
/etc/profile
/etc/profile.d/*.sh
用户个人:仅对当前用户生效
~/.bash_profile
功用:
① 用于定义环境变量
② 运行命令或脚本
(2)bashrc类:为非交互式登录的shell进程提供配置
全局:对所有用户都生效
/etc/bashrc
用户个人:仅对当前用户生效
~/.bashrc
功用:
① 定义本地变量
② 定义命令别名:alias
注意:仅管理员可以修改全局配置文件
登录类型:
交互式登录shell进程:
直接通过某终端输入账号和密码后登录打开的shell进程;
使用su命令:su - username,或者使用su -| USERNAME执行的登录切换
读取配置文件顺序:
/etc/profile->/etc/profile.d/*->/.bash_profile->/.bashrc->/etc/bashrc非交互式登录shell进程:
su USERNAME执行的登录切换
图形界面下打开的终端
运行脚本
读取配置文件顺序:
~/.bashrc->/etc/bashrc->/etc/profile.d/*
命令行中定义的特性,例如变量和别名作用域为当前shell进程的生命周期
配置文件定义的特性,只对随后新启动的shell进程有效;
让通过配置文件定义的特性立即生效:
(1) 通过命令行重复定义一次
(2) 让shell进程重读配置文件
a. source /PAHT/FROM/CONF_FILE
b. . /PAHT/FROM/CONF_FILE
举例:
1. 定义1个对所有用户都生效的命令别名,例如:lftps=‘lftp 172.168.0.1/pub’
定义变量别名,且对所有用户有效,则更改/etc/bashrc文件
[root@localhost etc]# vim bashrc
……
alias lftp='lftp 172.168.0.1/pub'
……
[root@localhost etc]# source bashrc //使其立即生效
[root@localhost etc]# alias //查看定义的命令别名
alias cp='cp -i'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l.='ls -d .* --color=auto'
alias lftp='lftp 172.168.0.1/pub'
alias ll='ls -l --color=auto'
alias ls='ls --color=auto'
alias mv='mv -i'
alias rm='rm -i'
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
2. 让所有用户登录时提示“Welcome to Linux World!”
在/etc/profile.d/目录下添加一个.sh文件
[root@localhost profile.d]# vim Welcome.sh
echo "Welcome to Linux World!"
保存退出
再重新登录一个用户
Xshell 6 (Build 0086)
Copyright (c) 2002 NetSarang Computer, Inc. All rights reserved.
Type `help' to learn how to use Xshell prompt.
[C:\~]$
Connecting to 127.0.0.1:36011...
Connection established.
To escape to local shell, press 'Ctrl+Alt+]'.
Last login: Tue Apr 9 20:14:59 2019 from 10.0.2.2
Welcome to Linux World!
[gqh@localhost ~]$
shell脚本是一个通过命令组合,搭配正则表达式、管道数据重流向等功能的文本文件,它有其固定的格式。
基本格式:
脚本文件的第一行:顶格,给出解释器路径,用于指明解释执行当前脚本的解释器程序文件
常用的解释器:
例如:
#!/bin/bash
echo "This is a test shell script!"
运行结果如下:
[root@localhost test]# chmod a+x test_sh.sh //添加可执行权限
[root@localhost test]# ./test_sh.sh //第一种运行方式
This is a test shell script!
[root@localhost test]# bash test_sh.sh //第二种运行方式,使用解释器直接运行,无需添加可执行权限
This is a test shell script!
[root@localhost test]# source test_sh.sh //第三种运行方式,无需添加可执行权限
This is a test shell script!
(1)变量
用于储存数据的一个名字就叫变量,实际上变量名指向一段内存空间。
变量名:变量名只能包含数字、字母和下划线,而且不能以数字开头
变量替换:把变量名出现的位置替换成其所指向的内存空间中数据
变量引用: $ {var_name},$ var_name
变量类型:bash把所有变量统统视作字符型
bash中的变量无需事先申明,相当于,把声明和赋值过程同时实现。
本地变量:作用域仅为当前shell进程
赋值:name=value
引用:$ {var_name},$ var_name
查看变量:set
撤销变量:unset name
环境变量:作用域为当前shell进程及其子进程
变量赋值:
①export name=value
或
name=value
export name
②declare -x name=value
或
name=value
decals -x name
-x:指定的变量会成为环境变量,可供shell以外的程序来使用;
-r:将变量设置为只读;
查看环境变量
①export
②declare -x
③print env或env
撤销环境变量:unset name
局部变量:作用域仅为某代码片段(函数上下文)
位置参数变量:当执行脚本的shell进程传递的参数
特殊变量:shell内置的有特殊公用的变量
(2)数组
例如:
$ {array_name[*]
或
$ {array_name[@]}
例如:
${#array_name[*]}
或
${#array_name[@]}
(3)参数传递
在执行shell脚本时,我们可以向脚本传递参数,脚本内获取参数的格式为:$n,
n表示数字:
$0表示脚本文件名;
$1为执行脚本的第一个参数
$2为执行脚本的第一个参数,以此类推
例如:
$ ./test.sh 1 2 3
Shell 传递参数实例!
执行的文件名:./test.sh
第一个参数为:1
第二个参数为:2
第三个参数为:3
(4)流程控制
选择控制: if或case
if语法格式:
①if语句
if condition
then
command1
command2
……
fi
②if else语句
if condition
then
command1
command2
……
else
command1
command2
……
fi
③if else-if else语句
if condition1
then
command1
command2
……
elif condition2
then
command1
command2
else
command1
command2
……
fi
case语法格式:
case VAL in
PATTERN1)
command1
command2
……
;;
PATTERN2)
command1
command2
……
;;
*)
command1
command2
……
;;
esac
循环控制: for或while或until
for语法格式:
格式1:固定循环
for val in parm1 parm2 parm3
do
程序段
done
格式2:
for (( 初始值化;限制值;执行步阶 ))
do
程序段
done
注意((后和))前有个空格
while语法格式:
while [ 条件判断 ]
do
done
条件判断为真,继续循环,为假,退出循环
until语法格式:
until [ 条件判断 ]
do
done
条件判断为假,继续循环,为真,退出循环
(5)数据流重导向
数据流重导向:将标准输入源重定向为其他输入源或者将标准输出/错误输出目标重定向到其他输出目标。
标准输入(stdin):代码为0,默认为键盘输入,我们可以使用<或<<重定向为其它输入,例如文件输入
标准输出(stdout):代码为1,默认为显示屏显示,我们可以使用>或>>重定向为其它输出,例如输出到文件
标准错误输出(stderr):代码为2,默认为显示屏显示,我们可以使用2>或2>>重定向为其它输出,例如输出到文件
<:表示原本需要用键盘输入的数据,改由文件来取代
<<:表示结束的输入字符
>:以覆盖的方法将数据输出到指定的文件或装置上
>>:以追加的方式将数据输出到指定的文件或装置上
合并正常和错误输出流:&>,&>>,COMMAND > FILE 2>&1
例如:ps -aux | grep ssh
将ps -aux的输出信息通过管道界定符当做grep的输入信息
(7)正则表达式
正则表达式是一种处理字符串的方法,通过一些特殊符号的辅助,让使用者达到某种目的。
这些特殊符号有以下这些:
OPTION:
-v:invert-match,反向匹配
-E:extended-regexp,扩展的正则表达式,与egrep一样
-i, --ignore-case,忽略大小写
-o:only-match
egrep:
与grep作用基本一致,不过其支持扩展的正则表达式,正则表达式中无需添加转义
基本正则表达式:
字符匹配:
.:匹配任意单个字符
[]:匹配指定范围内的任意单个字符
[^]:匹配指定范围外的任意单个字符
[:digit:][:lower:][:upper:]
匹配次数:(无需添加转移字符\)
:匹配其前面的字符任意次:0,1,多次
.:匹配任意长度的任意字符
?:匹配0个或1个任意字符
+:匹配其前面的字符至少一次
{m}:匹配其前面的字符m次
{m,n}:匹配其前面的字符至少出现m次,至多n次
{0,n}:至多n次
{m,}:至少m次,至多不限
位置锚定:
^:行首锚定,用于模式的最左侧
: 行 尾 锚 定 , 用 于 模 式 的 最 右 侧 P A T T E R N :行尾锚定,用于模式的最右侧 ^PATTERN :行尾锚定,用于模式的最右侧PATTERN:用于pattern来匹配整行
^ : 空 白 行 [ [ : s p a c e : ] ] ∗ :空白行 ^[[:space:]]* :空白行[[:space:]]∗:空行或包括空白字符的行
单词:非特殊字符组成的连续字符(字符串)都成为单词
<或\b:词首锚定,用于单词模式的左侧
>或\b:词尾锚定,用于单词模式的右侧
:匹配完整单词
相关举例:
1. 显示/etc/passwd文件中不以/bin/bash结尾的行
[root@localhost etc]# grep -v "/bin/bash$" passwd
2. 找出/etc/passwd文件中两位数或三位数的行
[root@localhost etc]# grep '\<[0-9]\{2,3\}\>' passwd
[root@localhost etc]# egrep '\<[0-9]{2,3}\>' passwd //支持扩展正则表达式
[root@localhost etc]# grep -E '\<[0-9]{2,3}\>' passwd //支持扩展正则表达式
3. 显示/proc/meminfo文件中以大写或小写S开头的行
[root@localhost proc]# grep -i "^S" /proc/meminfo
SwapCached: 0 kB
SwapTotal: 2097148 kB
SwapFree: 2097148 kB
Shmem: 9056 kB
Slab: 79100 kB
SReclaimable: 46228 kB
SUnreclaim: 32872 kB
4. 使用echo输出一个绝对路径,使用egrep取出路径名,类似执行dirname /etc/passwd的结果
[root@localhost Documents]# echo "$PWD"
/home/gqh/Documents
[root@localhost Documents]# echo "$PWD" | grep -Eo "^/.*/"
/home/gqh/
5. 找出ifconfig中的ip地址,要求结果只显示IP地址
[root@localhost Documents]# ifconfig | grep -Eo "(([[:digit:]]{1,2}|1[[:digit:]]{2}|2[0-5]{2})\.){3}([[:digit:]]{1,2}|1[[:digit:]]{2}|2[0-5]{2})"
10.0.2.15
255.255.255.0
10.0.2.255
127.0.0.1
255.0.0.0
192.168.122.1
255.255.255.0
192.168.122.255
sed:(stream editor)流编辑器
待补充
awk
待补充
作用: 将同一行里面的数据进行分解,处理的信息以行为单位
使用格式: cut OPTION… [FILE]…
Option:
-d CHAR:以指定的字符为分隔符;
-f FIELDSL:挑选出的字段
#:指定的单个字段,例如 -f1
#-#:指定的连续字段,例如-f2-3
#,#:离散的多个字段
作用: 指定文件按指定方式排序
使用格式:
sort [option]… [FILE]…
Option:
-t CHAR:指定分隔符
-n:按数值大小排序
-k#:用于排序比较的字段,例如-k3,以分隔后的第3个字段进行排序
-r:逆序
-f:忽略大小写
-u:重复的行只保留一份
作用: 以指定的单位统计数量,默认为单词数量
使用格式:
wc [OPTION]… [FILE]…
Option:
-c:bytes,显示字节数
-l:lines,显示行数
-w,words,显示词数
作用: 报告或移除重复的行
使用格式:
uniq [OPTION]… [INPUT [OUTPUT]]
作用: 逐行比较两个文件的不同之处
使用格式:
diff OLD_FILE NEW_FILE > PATCH_FILE
作用: 打补丁
使用格式:
patch [-blNR][ -c| -e| -n][-d dir][-D define][-i patchfile]
[-o outfile][-p num][-r rejectfile][file]
作用: 从标准输入删除或替换字符,并将结果写入标准输出。
使用格式:
tr string1 string2
将string1所包含的每个字符都替换成string2中相同位置的字符
tr {-d | -s} String1
删除string1中包含的每一个字符
[:space:] ↩︎