linux基础知识之shell编程基础

一、shell基础

1. 什么是shell?

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)的增强版。
linux基础知识之shell编程基础_第1张图片

2. 什么是shell脚本?

shell脚本是利用shell的功能所写的一个程序,这个程序是用纯文本文件,将一些shell的语法与指令写在里面,搭配正规表示法、管线命令与数据流重导向等功能,已达到我们想要的处理母的。
shell脚本有点类似于我们在windows下的批处理文件(.bat).
shell脚本是一种过程式的编程,解释运行,依赖于外部程序文件运行。它不同于其它编译型语言(c、c++,java等),它的源代码在运行时启动解释器,由解释器边解释变运行,而编译型语言是源代码经过编译器编译后的二进制可执行文件。

3. 如何运行shell脚本?

运行shell脚本有3种方式:
(1)给脚本添加可执行权限,直接运行文件
例如:chmod +x /PATH/TO/SCRIPT_FILE
(2)直接调用命令解释器执行程序
例如:bash /PATH/TO/SCRIPT_FILE
(3)使用source运行
source又被称为“点”命令,通常用于重新执行刚修改的初始化文件,使之立即生效。
source命令影响shell进程本身,在脚本执行过程中,无子进程的创建和消亡
注意:
①脚本中的空白行都被忽略
②脚本中,所有以#开头的行,都会被视作注释行而被忽略,即为注释行
③shell脚本的运行是通过运行一个子shell进程实现的。

4. bash的配置文件

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编程

1. 基本格式

shell脚本是一个通过命令组合,搭配正则表达式、管道数据重流向等功能的文本文件,它有其固定的格式。
基本格式:
脚本文件的第一行:顶格,给出解释器路径,用于指明解释执行当前脚本的解释器程序文件
常用的解释器:

  • #!/bin/sh
  • #!/bin/bash
  • #!/bin/python
例如:
#!/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!

2. 基本语法

(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=(value1 … valuen),元素用“空格”隔开

    array_name[0]=value1
    array_name[1]=value2
    array_name[2]=value3
  • 读取数组
    ${array_name[index]}
  • 获取数组中的所有元素
    使用@ 或 * 可以获取数组中的所有元素

    例如:
    $ {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
linux基础知识之shell编程基础_第2张图片

(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
linux基础知识之shell编程基础_第3张图片

  • 双向重导向:tee
    linux基础知识之shell编程基础_第4张图片
    tee会同时将数据流分送到文件与屏幕去。
    (6)管道
    管道我们使用“|”这个界定符号,它将一个指定的输出数据作为另一个指令的输入,输出指的是标准输出,忽略错误输出。
    linux基础知识之shell编程基础_第5张图片

例如:ps -aux | grep ssh
将ps -aux的输出信息通过管道界定符当做grep的输入信息
在这里插入图片描述
(7)正则表达式
正则表达式是一种处理字符串的方法,通过一些特殊符号的辅助,让使用者达到某种目的。
这些特殊符号有以下这些:

  • 字符匹配:
    .:匹配任意单个字符
    []:匹配指定范围内的任意单个字符
    [^]:匹配指定范围外的任意单个字符
    [:digit:][:lower:][:upper:]
  • 匹配次数:(无需添加转移字符\)
    :匹配其前面的字符任意次:0,1,多次
    .
    :匹配任意长度的任意字符
    ?:匹配0个或1个任意字符
    +:匹配其前面的字符至少一次
    {m}:匹配其前面的字符m次
    {m,n}:匹配其前面的字符至少出现m次,至多n次
    {0,n}:至多n次
    {m,}:至少m次,至多不限
  • 位置锚定:
    ^:行首锚定,用于模式的最左侧
    $:行尾锚定,用于模式的最右侧
    ^PATTERNKaTeX parse error: Expected group after '^' at position 17: …用于pattern来匹配整行 ^̲:空白行
    1*$:空行或包括空白字符的行
  • 单词:非特殊字符组成的连续字符(字符串)都成为单词
    \<或\b:词首锚定,用于单词模式的左侧
    \>或\b:词尾锚定,用于单词模式的右侧
    \:匹配完整单词
  • 分组及引用
    ():将一个或多个字符捆绑在一起,当做一个整体进行处理
    例如:\(x\y)*ab,将xy当做一个整体
    分组括中的模式匹配到的内容会被正则表达式引擎自动自路与内部的变量中,这些变量为:
    \1:模式从左侧起,第一个左括号以及与之匹配的右括号之间的模式所匹配到的字符
    \2:模式从左侧起,第二个左括号以及与之匹配的右括号之间的模式所匹配到的字符
    \3…
    例如:grep “(l…e).*\1”,\1相当于(l…e)

3. 常用指令

(1)文本处理三剑客:grep,sed,awk

  • grep:(global search regular expression and print out the line),文本过滤工具
    作用: 文本搜素工具,根据用户指定的“模式(过滤条件)”对目标文本逐行进行匹配检查,打印匹配的行
    模式: 由正则表达式的元字符及文本字符所编写出的过滤条件
    使用格式:
    grep [option] PATTERN [FILE…]
    PATTERN:正则表达式匹配

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
    待补充

(2)撷取命令:cut

作用: 将同一行里面的数据进行分解,处理的信息以行为单位
使用格式: cut OPTION… [FILE]…

Option:
-d CHAR:以指定的字符为分隔符;
-f FIELDSL:挑选出的字段
#:指定的单个字段,例如 -f1
#-#:指定的连续字段,例如-f2-3
#,#:离散的多个字段

(3)排序命令:sort

作用: 指定文件按指定方式排序
使用格式:
sort [option]… [FILE]…

Option:
-t CHAR:指定分隔符
-n:按数值大小排序
-k#:用于排序比较的字段,例如-k3,以分隔后的第3个字段进行排序
-r:逆序
-f:忽略大小写
-u:重复的行只保留一份

(4)单词统计:wc(wordcount)

作用: 以指定的单位统计数量,默认为单词数量
使用格式:
wc [OPTION]… [FILE]…

Option:
-c:bytes,显示字节数
-l:lines,显示行数
-w,words,显示词数

(5)文本去重:uniq

作用: 报告或移除重复的行
使用格式:
uniq [OPTION]… [INPUT [OUTPUT]]

(6)文本比较:diff

作用: 逐行比较两个文件的不同之处
使用格式:
diff OLD_FILE NEW_FILE > PATCH_FILE

(7)patch

作用: 打补丁
使用格式:
patch [-blNR][ -c| -e| -n][-d dir][-D define][-i patchfile]
[-o outfile][-p num][-r rejectfile][file]

(8)文本替换:tr

作用: 从标准输入删除或替换字符,并将结果写入标准输出。
使用格式:
tr string1 string2
将string1所包含的每个字符都替换成string2中相同位置的字符
tr {-d | -s} String1
删除string1中包含的每一个字符


  1. [:space:] ↩︎

你可能感兴趣的:(linux,linux基础)