Shell

Shell 基础

·24 分钟阅读·9406 字

Shell 脚本编程基础:变量、条件、循环、函数、正则

📋 目录

一、shell基础

(1)shell种类

shell种类:

/bin/sh 是 bash shell的一个快捷方式

/bin/bash #bash shell是大多数Linux默认的shell,包含的功能几乎可以涵盖shell所有的功能

/sbin/nologin 表示非交互,不能登录操作系统

/bin/dash #小巧,高效,功能相比少一些

/bin/tcsh   是 csh 的增强版,完全兼容csh

/bin/csh 具有 C 语言风格的一种 shell,具有许多特性,但也有一些缺陷

(2)shell的调用

  1. 查看:系统可用的 Shell

chsh -l

  1. 查看:<用户>当前使用的

echo $SHELL 查看:<当前用户>的<默认Shell>

  1. 永久更改:<用户>的<登录 Shell>

useradd user01

chsh -s /bin/sh user01

cat /etc/passwd | grep ^user01

  1.  <Shell 脚本>声明:<Shell 命令行解释器>

 #!/bin/bash:声明<Shell 脚本>的<Shell 命令行解释器>

★【#!】用于声明:<本脚本>需要采用的<命令行解释器>。

  1. 调用shell来执行命令

bash -c date # 调用bash

sh -c date 调用 sh

(3)shell变量

命名规则: 可以由字母,数字,下划线组成,不能以数字开头,不能是关键字,见名知意

定义方式:变量名= “变量值”

提取变量: $变量名 或 ${变量名}

(4)数组变量

①定义数组 数组名=(值1 值2 …值n)

name=(tom mary natasha)

name[3]=jim

②查看数组中某个元素值

echo ${name[0]}

tom

echo ${name[2]}

natasha

③查看数组的下标

echo ${!name[@]}

④数组的遍历

echo ${name[*]}

tom mary natasha

echo ${name[@]}

tom mary natasha

⑤显示数组中元素的个数

echo ${#name[@]}

echo ${#name[*]}

⑥取消数组

unset name[索引] 利用下标删除目标

unset name 直接删除整个数组

(5)变量类型

变量分为本地变量、环境变量、内置变量

本地变量:当前用户自定义的变量。当前进程中有效,其他进程及当前进程的子进程无效。

环境变量:当前进程有效,并且能够被子进程调用。

内置变量:系统变量,shell本身已经固定好了它的名字和作用。

①环境变量

查看当前用户的环境变量: env

查询当前用户的所有变量(临时变量与环境变量):set

将当前变量变成环境变量:export

②内置变量

$?:上一条命令执行后返回的状态,当返回状态值为0时表示执行正常,非0值表示执行异常或出错

$$:当前所在进程的进程号 echo $$ eg:kill -9 echo $$ = exit 退出当前会话

$!: 后台运行的最后一个进程号 (当前终端)

!$ 调用最后一条命令历史中的参数

!! 调用最后一条命令历史

$#:脚本后面接的参数的个数

$*:脚本后面所有参数,参数当成一个整体输出,每一个变量参数之间以空格隔开

$@: 脚本后面所有参数,参数是独立的,也是全部输出

$0: 当前执行的进程/程序名 echo $0

$1~$9 位置参数变量

${10}~${n} 扩展位置参数变量 第10个位置变量必须用{}大括号括起来

(6)脚本运行方法

 

**(7)**用户环境变量配置文件

$HOME/.bashrc 当前用户的bash信息(aliase、umask等) (用户级)

$HOME/.bash_profile 当前用户的环境变量(用户级)

$HOME/.bash_logout 每个用户退出当前shell时最后读取的文件 (用户级)

/etc/bashrc 使用bash shell用户全局变量 (系统级)

/etc/profile 系统和每个用户的环境变量信息 (系统级)

用户登录系统读取相关文件的顺序:

/etc/profile——>$HOME/.bash_profile——>$HOME/.bashrc——>/etc/bashrc——>$HOME/.bash_logout

(8)shell脚本中的引号

★ <""双引号> 是:<部分引用>,可以识别<特殊符号>

★ <”单引号> 是:<完全引用>,不能识别<特殊符号>

二、shell辅助命令

(1)标准输入输出及重定向

①标准输入输出概念

stdin 标准输入 是指:来自键盘输入或者其他命令的标准(错误)输出的数据。

stdout标准输出就是终端显示器。 shell 的所有输出(包括shell 中运行的程序和脚本)会被定向到标准输出。

②echo命令

将指定内容输出到屏幕(标准输出)

常用选项

-n: 输出结果后面没有换行符

-e:启用转移符\ (需要输出特殊符号的时候:\n \t)

\n 换行

\t 横向制表符

③标准输出重定向

输出重定向是指把本应该输出到屏幕的内容重新导向其他地方,比如导入文件中。标准输出又分为标准输出和标准错误输出。

stdout 标准输出是指:一个命令执行之后的正确结果输出,在输出重定向是用数字1表示,也可以省略不写。

stderr 标准错误输出是指:一个命令执行之后的报错信息输出,在输出重定向是用数字2表示。

★ 输出重定向符号: > 和 >>

: 表示覆盖式重定向

: 表示追加式重定向

④标准输入重定向

输入重定向是指把本应该重键盘输入的来源换成从文件或屏幕中的内容进行输入。

★ 输出重定向符号: < 和 <<

< : 表示覆盖式重定向

<<: 表示追加式重定向

⑤管道符| 与xargs命令

★ 管道符

作用:将前一个命令的标准输出,作为后一个命令的标准输入。

★ xargs

作用:部分命令不支持通过管道符传入的标准输入,可以使用xargs来传递输入(比如rm,kill等)

(2)grep命令和正则表达式

① grep命令

★ 功能:

▶ 筛选过滤出:包含<匹配字符串>的<整行>

★ 语法:

grep [选项]… PATTERN [FILE]…

★ PATTERN

就是正则|表达式,默认情况,grep命令使用基本正则

★ 选项:

-i ## 表示:忽略大小写

-E ## 表示:启用<扩展正则>

-P ## 表示:启用<Perl正则>

-r ## 表示:递归操作

-l ## 输出:包含<匹配内容>的<文件名>

-o ## 表示:仅输出<匹配内容本身>,默认情况下,是输出:包含<<匹配内容>的<一行数据>

-q ## 表示:不输出,静默操作,通常用于:条件判断

-v ## 表示:仅输出<不匹配的数据行> ▶ 注意:是<不匹配的行>

-c ## 显示:匹配的<数据行>的<行总数>

②正则表达式

Ⅰ、bash通配符

▶ Bash通配符:是Bash Shell自带的

  • 表示:匹配任意的一个或多个字符

? 表示:匹配任意的一个字符

[] 表示:匹配[xyx]列表中任意的一个字符

Ⅱ、基本正则元字符

 

Ⅲ、扩展正则元字符

 

**(3)**shell辅助命令

①sort

★ 命令选项:

-g 按一般数值排序

-n 按字符串数值排序

-r 逆序/降序排序(默认是:升序)

-f 忽略<字母大小写>

-b 忽略<前导的空白区域>

-k 指定:字段编号.字段字符位置

-o 将<排序结果>回写入<原文件>

②uniq

作用:uniq 命令删除文件中的重复行。 uniq 命令读取由 InFile 参数指定的标准输入或文件。该命令首先比较相邻的行,然后除去第二

行和该行的后续副本。

★ 命令选项:

-c 统计,在输出行前面加上每行在输入文件中出现的次数。

-d 仅显示重复行。

-u 仅显示不重复的行。

③wc

作用:统计指定文件中的字节数、字数、行数, 并将统计结果显示输出。

★ 命令选项:

  • c 统计字节数。

  • l 统计行数。

  • w 统计字数,单词数。

④cut

功能:将每个文件中每一行的匹配部分(按指定规则截取)打印到标准输出。

语法:cut OPTION… [FILE]…

★ 常用选项:

-d, —delimiter=DELIM 设置:单个自定义分隔符,需使用单引号 或 双引号

※ 默认为:Tab制表符 ◀◀◀

※ 文件中的连续多个分隔符,只有第1个有效,剩余的视为普通字符

※ 只能和 -f选项 一起使用

-f, —fields=LIST 按字段进行选择,承认分隔符,以分隔符区分字段

※ 除非指定了-s选项,否则还会打印任何不包含分隔符的行

-s, —only-delimited 不打印没有包含分界符的行

-c, —characters=LIST 按字符进行选择,不承认分隔符

-b, —bytes=LIST 按字节进行选择,不承认分隔符

-n ※ 和 -b选项 一起使用:不分割<多字节字符>,如:汉字

※ 在中,是用<3个字节>来显示一个<汉字>

—complement 补全选中的<字节、字符、字段>

—output-delimiter=TRING 使用指定的字符串作为输出分界符,默认采用输入的分界符

☞ 选项说明:

针对 -b,-c,-f 这三个选项,只能使用其中的一个。

每一个LIST列表,都是一个范围值,可以使用,逗号来分隔多个范围值。

范围值的格式如下:

N 仅仅<第N个>的<字节、字符、域>

N- 从<第N个>到<行尾>之间(包括<第N个>)的所有<字节、字符、字段>

N-M 从<第N个>到<第M个>之间(包括<第M个>)的所有<字节、字符、字段>

-M 从<第1个>开始到<第M个>之间(包括<第M个>)的所有<字节、字符、字段>

⑤tr

作用:tr 命令可以对来自标准输入的字符进行替换、压缩和删除。

语法:tr [选项] 字符集1 字符集2

字符集1:指定要转换或者删除的原字符集。当执行转换操作时,必须使用参数“字符集2”指定转换的目标字符集。但执行删除操

作时,不需要参数“字符集2” 。

★ 常用选项

-s 替换连续出现的字符

-d 删除字符

⑥tee

作用:主要被用来向standout(标准输出流,通常是命令执行窗口)输出的同时也将内容输出到文件

语法:tee [选项]… [文件]…

★ 常用选项

-a, —append内容追加到给定的文件而非覆盖

⑦watch

作用:watch命令可以实时全屏监控当前命令执行的动态变化结果。

语法:watch [选项] 命令

★ 常用选项

-n 每隔几秒刷新一次结果(默认是每隔2秒刷新一次)

-d 高亮显示命令执行结果的变化

-t 隐藏全屏顶端的时间间隔,命令信息

⑧sleep与wait

sleep 命令

功能:暂停一段时间,时间单位可以是 s m h d,默认是 s(秒)

wait 命令

功能:

▶ wait命令 是用来阻塞当前进程的执行,直至当前进程的指定子进程或者当前进程的所有子进程返回状态为0,执行结束之后,方

才继续执行。

▶ 使用 wait命令可以在bash脚本的多进程执行模式下,起到一些特殊控制的作用。

⑨read

作用:用于脚本与用户的交互,可以将用户输入的值存入变量。

★ 常用选项

-p:设置提示信息

-e:用户输入的时候允许回退

-s:不显示输入的内容 (密码输入的时候使用)

-t:timeout 设置超时时限,单位:秒

⑩timeout

作用: 控制command命令的执行时长

语法:timeout [选项] N[s|m|d] command命令 [参数]…

N[s|m|d] 设置命令的执行时长为N,默认单位为s秒,还可以是m分钟、h小时、d天

★ 常用选项

-s, —signal=SIGNAL 设置终止command命令进程的信号名,默认为TERM信号

TERM/15 优雅的终止<command命令进程>(留有时间,非立即,非强制)

SIGKILL/9 强制的终止<command命令进程>(不留时间,立即执行,只能由管理员发出)

-k, —kill-after=N 设置当第一个终止信号发出N时长之后,如果command命令进程仍在运行,则执行SIGKILL强制终止。

⑪dirname 和basename

dirname

指令去除文件名中的非目录部分,删除最后一个“\”后面的路径,显示父目录。 dirname返回文件所在目录路径,而basename则相

反,去掉路径返回最后的文件名。

语法:dirname [选项] 参数

basename

指令用于打印目录或者文件的基本名称,显示最后的目录名或文件名。

语法:basename [选项] 参数

三、流程控制语句

(1)算数计算

①整数计算

Ⅰ、let命令

Ⅱ、expr命令

1、数值与运算符号之间需要用空格隔开,否则无法进行算术运算。

2、使用expr命令进行乘法运算时,需要将”乘号”转义,否则会报错。

Ⅲ、使用算数语法$(( 算数表达式))

Ⅳ、使用算数语法$[算数表达式]

②小数运算

bc命令

bc命令是linux下最常用的”计算器” ,我们可以借助bc命令进行算术运算,使用这种方法的优势就是支持小数运算。

注意:在使用”除法”时,需要指定小数点精度,否则运算结果中不会包含小数,使用scale指定小数点精度。

处理整数:

echo “(1+2)*(3+4)” | bc # 计算结果 = 21

echo “10/3” | bc # 计算结果 = 3 (不支持浮点小数)

处理小数:

echo “scale=2;10/3” | bc # 计算结果 = 3.33 ( 支持浮点小数)

(2)条件判断

①test

test命令:用于判断表达式是否成立,成立返回0,不成立则返回其他数字。

格式1:test 条件表达式

格式2:[ 条件表达式 ] (记住左右都要有空格)、

Ⅰ、文件判断

格式:[ 操作符 文件或者目录 ]

常用的测试操作符:

-d:用于测试是否是目录

-e:测试目录或文件是否存在

-f:测试文件是否存在且为普通文件

-r:测试当前的用户是否有读的权限

-w:测试当前用户是否有写的权限

-x:测试当前用户是否具有可执行权限

-L:测试是否为符号链接

-b:测试是否为块设备文件

-c:测试是否为字符型特殊文件

Ⅱ、判断整数值大小

格式:[ 整数1 操作符 整数2 ]

常用的测试操作符:

-eq:等于

-ne:不等于

-gt:大于

-lt:小于

-le:小于等于

-ge:大于等于

Ⅲ、判断字符串

格式:[ 字符串1 操作符 字符串2 ]

或者:[ 操作符 字符串 ]

常用的测试操作符:

-z STRING # 判断:字符串是否为空

-n STRING # 判断:字符串是否为非空

STRING1 = STRING2 # 判断:两个字符串内容是否相同

STRING1 != STRING2 # 判断:两个字符串内容是否不同

Ⅳ、逻辑操作

格式:[ 条件表达式1 逻辑操作符 条件表达式2 ]

或者:[ 逻辑操作符 条件表达式 ]

常用的逻辑操作符:

! EXPR # 执行:逻辑取反

EXPR1 -a EXPR2 # 执行:逻辑与

EXPR1 -o EXPR2 # 执行:逻辑或

Ⅴ、命令连接符

 

(3)流程控制语句

Ⅰ、单分支语句

单分支 if 条件语句最为简单,就是只有一个判断条件,如果符合条件则执行某个程序,否则什么事情都不做。

语法如下:

if [条件判断];then 条件判断可以是判断表达式,也可以是其他命令

命令块

fi

或者

if [条件判断]

then

命令块

fi

Ⅱ、双分支语句

在双分支 if 条件语句中,当条件判断式成立时,则执行某个命令块;当条件判断式不成立时,则执行另一个命令块。

语法如下:

if [条件判断]

then

命令块 当条件判断成立时执行

else

命令块 当条件判断不成立时执行

fi

Ⅲ、多分支语句

在多分支 if 条件语句中,允许执行多次判断。也就是当条件判断式 1 成立时,执行命令块1;当条件判断式 2 成立时,执行命令块2;依次类

推,当所有条件不成立时,执行最后的程序。

语法如下:

if[条件判断式1]

then

命令块1 # 当条件判断式1成立时

elif [条件判断式2]

then

命令块2 # 当条件判断式2成立时

…省略更多条件…

else

命令块 # 当所有条件都不成立时执行

fi

(4)case语句

语法格式:

case 变量值 in

模式1)

命令块 1

;;

模式2)

命令块 2

;;

) # ”“代表任意

默认命令序列

esac

四、循环语句

(1)for循环语句

格式一:算数条件判断for循环(c风格)

语法格式:

for ((EXPR1; EXPR2; EXPR3)) ;

do

COMMANDS ;

done

格式二:遍历单词序列 for循环

for 变量 in 单词序列 ;

do

COMMANDS;

done

(2)while循环语句

语法格式:

while [条件表达式]

do

命令块

done

(3)until

语法格式:

until [条件表达式]

do

命令块

done

(4)循环控制命令

exit 退出整个程序

break 结束当前循环,或跳出本层循环

continue 忽略本次循环剩余的代码,直接进行下一次循环

(5)随机数

在Linux Shell中,生成随机数是一个常见的需求。无论是在写shell脚本中还是在命令行中,生成随机数都可以帮 助我们解决很多问题。在bash shell中,还有一个环境变量$RANDOM,它会在每次访问时生成一个随机数,随机数范围为0-32767。

(6)shell函数

语法一:

function 函数名

{

命令序列

[返回值]

}

语法二:

函数名()

{

命令序列

[返回值]

}

调用函数的方法:

函数名 [参数1] [参数2]

四、文本处理工具

(1)sed

sed 是一个用于:过滤并转换文本行的流编辑器

①sed工作原理

 

②sed 的优点: 

Ⅰ、Sed 不会导致内存不足

Sed 只会缓存<一行的内容>在<模式空间>,这样的好处是:

● sed可以处理<大文件>,而不会有任何问题

● 不像一些编辑器,因为要一次性载入<文件的一大块内容>到<缓存>中,从而导致<内存不足>

Ⅱ、 Sed 是一个<非交互式>的<字符流编辑器>。

所谓<非交互式> 是指使用sed只能在命令行下输入编辑命令来编辑文本,然后在屏幕上查看<标准输出>。

所谓<流编辑器> 是指sed每次只从文件(或输入)读入一行,并将<处理结果>标准输出到<屏幕>,然后,读入<下一行>。整个文件像流水一样,被<逐行读入>、<逐行处理>,然后<逐行输出>。

Ⅲ、 Sed 不是在源输入上直接进行处理的。

sed 不是在源输入上直接进行处理的,而是先将读入的行放到缓冲区中,对缓冲区中的内容进行处理,处理完毕后,直接将处理结果标准输出到屏幕上,而不会写回<源文件>。除非:用sed -i将输出重定向到源文件。

③sed 的语法结构

★ 语法1:sed [options] script filename # 直接在命令行中,定义并执行:一系列sed 操作指令

★ 语法2:sed [options] -f scriptfile filename # 通过调用scriptfile操作指令文件,来执行:一系列sed 操作指令

备注:

[options] 定义:sed 命令选项

script 是指:命令的执行脚本,即:命令行的sed 操作指令

一般由地址匹配和动作指令组成。

-f scriptfile 是指:包含sed 操作指令的文本文件,用 -f 选项来调用

filename 指定:sed 操作对象(即:文件)

sed 可以接受标准输入,可以接受|管道符

④sed 的常用选项

-r # 启用扩展正则表达式,但是,需要注意元字符的调用格式。

扩展的正则表达式中,如果元字符与sed专用字符发生冲突,则需使用【\转义符】。

-e # 执行多个script脚本,如:-e ‘script01’ -e ‘script02’ -e ‘script03’

注意:多个script脚本是顺序执行的,前一个script脚本的行输出信息,是后一个script脚本的行输入信息。

前一个script脚本未匹配未执行,不会影响后一个script脚本的正常执行。

-n # 抑制sed命令的<标准输出

默认情况下,sed命令将标准输出:未处理的行数据和已处理的行结果。

-i # 将标准输出覆盖式回写到源文件,直接修改源文件。

⑤sed常用指令(子命令动作)

p:print,打印

d: delete,删除

! : 非 ,放在命令前面表示取反

i:在匹配行前面插入新行添加指定内容

a:在匹配行后面插入新行添加指定内容

c:用新内容直接替换匹配的整行

s:用新内容替换指定的旧文本内容

y:转换的命令,对应转换

r:将指定的文件内容添加到符合条件的行处 r后接文件路径

w:将地址指定的范围内的行另存至其他指定文件中 直接可以对文件操作

(2)awk

★ AWK 是一种解释执行的编程语言,它非常的强大,被设计用来专门处理文本数据。

★ AWK 的名称是由它们设计者的名字缩写而来 —— Afred Aho, Peter Weinberger 与 Brian Kernighan。

★ AWK 可以做非常多的工作,下面只是其中的一小部分:

☞ 文本处理

☞ 生成格式化的文本报告

☞ 进行算术运算

☞ 字符串操作 等

★ awk 与 sed、grep的比较:

sed 是一个基于行字符流,执行整行处理的文本处理工具,

awk 是一个基于行字符流,精细到列处理的文本处理工具。

①awk工作流程

AWK 执行的流程非常简单:读(Read)、执行(Execute)与重复(Repeat)

 

②awk语法格式

awk由三个部分组成:开始(begin)、主体、结束(end),开始(begin)、结束(end)这两部份可选,一般用于格式化输出。

begin:在主体前运行,只运行一次

end :在主体结束后运行,只执行一次

★ 语法:

awk [option] ‘pattern{action}’ filename

pattern:模式匹配,匹配指定行。可以使用行号变量、正则以及条件

action:执行操作,比如常用命令print:打印输出

★ 常用选项

-F 定义字段分割符号,默认的分隔符是空格

-v 定义变量并赋值

★工作模式:

1.行工作模式,读入一行文件,存在”$0”里

2.使用内置变量FS(字段分隔符)分割一行,存在$1-$100

3.输出时也是用内置变量OFS,输出该行

③awk内部变量:

$0 当前处理行的所有记录

$n 文件中每行以间隔符号分割的不同字段

NF 当前记录的字段数(列数)

$NF 最后一列 $(NF-1)表示倒数第二列

FNR/NR 行号

FS 定义间隔符

OFS 定义输出字段分隔符,默认空格 ‘BEGIN{OFS= “\t”};print $1,$3}’

RS 输入记录分割符,默认换行,一般不更改

ORS 输出记录分割符,默认换行 ,一般不更改

FILENAME 当前输入的文件名

关联文档

  • 脚本与编程 — Shell/Python 编程
  • ../../linux/system/Linux — Linux 命令 -面试题/Shell 脚本面试题 — Shell 面试题