Shell脚本基础

Shell是一个命令解释器,它接收应用程序/用户命令,然后调用操作系统内核。

Shell还是一个功能相当强大的编程语言,易编写、易调试、灵活性强。

https://blog.csdn.net/Jackson00709/article/details/106086756

Shell概述

shell是一个命令行解释器,它接收应用程序/用户命令,然后调用操作系统内核

脚本入门

脚本格式

脚本以#!/bin/bash开头(指定解析器)

helloworld

# 创建脚本
[linux@localhost datas]$ cat helloworld.sh 
#!/bin/bash
echo "hello huangxb"

# 执行脚本方式1
[linux@localhost datas]$ bash helloworld.sh 
hello huangxb

# 执行脚本方式2
[linux@localhost datas]$ ./helloworld.sh
-bash: ./helloworld.sh: 权限不够

方式1,本质是bash解析器帮你执行脚本,所以脚本本身不需要执行权限;方式2,本质是脚本自己需要执行,所以需要执行权限

修改文件权限的命令是

chmod [option] filename

其中[option]表示各种权限选项。具体如下:

  • r(或4):读取权限

  • w(或2):写入权限

  • x(或1):执行权限

    此外还可以指定权限的获取者,也就是指定将当前权限赋予之前提到的三个部分的左中右哪个部分:

    • u:文件所有者

    • g:文件所有者所在的组的用户

    • o:其他组的用户

      权限的授予可采用操作符“+”,而“-”表示收回权限。

示例[1]:授予文件所有者以ex1-2.sh文件的执行权限

[root@linux chapter1]# chmod u+x ex1-2.sh
[root@linux chapter1]# 11
total 4
-rwxr--r--	l	root	root	116		Dec 18 23:11	ex1-2.sh

示例[2]:采用数字表示法来授予文件所有者以ex1-2.sh文件的执行权限

[root@linux chapter1]# chmod 744 ex1-2.sh
[root@linux chapter1]# 11
total 4
-rwxr--r--	l	root	root	116		Dec 18 23:11	ex1-2.sh

上面的第二份代码中的“744”分别表示文件所有者、文件所有者所在的组的用户、其他组的用户的权限。其中“7”表示了4+2+1也就是三个权限的数值之和,表明了“所有权限”。可见数值方法可以很方便地同时赋予用户权限。

多命令处理

  • 在linux家目录下创建一个bangzhang.txt并在文件中写入"I IOVE YOU"字符
#!/bin/bash
cd /home/linux/
touch banzhang.txt
echo "I LOVE YOU" >> banzhang.txt
1234

Shell中的变量

常用系统变量

$HOME $PWD $SHELL $USER

[linux@localhost datas]$ echo $HOME
/home/linux
[linux@localhost datas]$ echo $PWD
/home/linux/datas
[linux@localhost datas]$ echo $SHELL
/bin/bash
[linux@localhost datas]$ echo $USER
linux

自定义变量

基本语法

  1. 定义变量:变量=值 等号两边不能留有空格
  2. 撤销变量:unset 变量
  3. 输出变量:echo $变量
  4. 声明静态变量: readonly 变量,注意:不能unset
[linux@localhost datas]$ A=1
[linux@localhost datas]$ echo $A
1
[linux@localhost datas]$ unset A
1234

自定义的变量是有作用范围的,通过ps -f 查看当前bash,子类bash自定义的变量为局部变量,只能在自己的bash范围下有效,父类bash是看不到的

变量定义规则

  1. 变量名称可以由字母,数字和下划线组成,不能以数字开头,环境变量名建议大写
  2. 等号两侧不能有空格
  3. 在bash中,变量默认类型都是字符串类型,无法直接进行数值运算
  4. 变量的值如果有空格,需要使用双引号或单引号括起来
[linux@localhost datas]$ D="A B C"
[linux@localhost datas]$ echo $D
A B C
123
  1. 可把变量提升为全局变量,可供其他shell程序使用
    export 变量

特殊变量

$n-获取控制台输入的参数

$n (描述:n为数字,$0代表脚本名称,10以内参数用$1-9 表 示 , 10 以 上 的 需 要 用 大 括 号 包 含 ${10})

[atguigu@hadoop101 shells]$ touch parameter.sh
[atguigu@hadoop101 shells]$ vim parameter.sh
#!/bin/bash
echo '==========$n=========='
echo $0
echo $1
echo $2
[atguigu@hadoop101 shells]$ chmod 777 parameter.sh
[atguigu@hadoop101 shells]$ ./parameter.sh cls xz
==========$n==========
./parameter.sh
cls
xz

echo '$n'使用单引号而不是双引号,使用双引号括起来时,会以为$n为一个变量,我们要让他原封不动的输出来

$#-获取输入参数个数

$# (功能描述:获取所有输入参数个数,常用于循环,判断参数的个数是否正确以及加强脚本的健壮性)

[atguigu@hadoop101 shells]$ vim parameter.sh
#!/bin/bash
echo '==========$n=========='
echo $0
echo $1
echo $2
echo '==========$#=========='
echo $#
[atguigu@hadoop101 shells]$ chmod 777 parameter.sh
[atguigu@hadoop101 shells]$ ./parameter.sh cls xz
==========$n==========
./parameter.sh
cls
xz
==========$#==========
2

$* 和$@

  • $* (描述:代表命令行中所有的参数,把所有参数看成一个整体
  • $@ (描述:也代表命令行中所有的参数,不过把每个参数区分对待
[atguigu@hadoop101 shells]$ vim parameter.sh
#!/bin/bash
echo '==========$n=========='
echo $0
echo $1
echo $2
echo '==========$#=========='
echo $#
echo '==========$*=========='
echo $*
echo '==========$@=========='
echo $@
[atguigu@hadoop101 shells]$ ./parameter.sh a b c d e f g
==========$n==========
./parameter.sh
a
b
==========$#==========
7
==========$*==========
a b c d e f g
==========$@==========
a b c d e f g

$?

$? (描述:最后一次执行命令的状态,如果这个变量的值为 0,证明上一 个命令正确执行;如果这个变量的值为非 0(具体是哪个数,由命令自己来决定),则证明 上一个命令执行不正确了。)

[atguigu@hadoop101 shells]$ ./helloworld.sh
hello world
[atguigu@hadoop101 shells]$ echo $?
0

运算符

  1. $((运算式)) 或 $[运算式]
  2. expr +,-,*,/,% 加减乘除取余
    expr运算符间要有空格
# 计算2+3
[linux@localhost datas]$ expr 2 + 3
5

# 计算(2+3)*4
## 方式1
[linux@localhost datas]$ expr `expr 2 + 3` \* 4
20

## 方式2
[linux@localhost datas]$ s=$[(2+3)*4]
[linux@localhost datas]$ echo $s
20
12345678910111213

expr进行乘运算时不能直接用 * ,需要进行转义:\*

如果要进行计算整体划分,还需要用反引号括起来``

条件判断

基本语法

test condition

[ condition ] (注意 condition前后要有空格)

注意:条件非空即为 true,[ atguigu ]返回 true,[ ] 返回 false。

# test condition判断
[root@hadoop111 ~]# a=hello
[root@hadoop111 ~]# test $a = hello
[root@hadoop111 ~]# echo $?
0
[root@hadoop111 ~]# test $a = Hello
[root@hadoop111 ~]# echo $?
1
# [ condition ]判断
[root@hadoop111 ~]# [ $a = hello ]
[root@hadoop111 ~]# echo $?
0
[root@hadoop111 ~]# [ $a = Hello ]
[root@hadoop111 ~]# echo $?
1

通过$?来判断test condition、[ condition ]的返回值,进而达到判断真假

使用[ condition ]来判断,不仅括号两边要有空格,内部的等号也要有空格

常用判断条件

两个整数之间比较

符号 描述
-lt (less than)小于
-le (less equal) 小于等于
-eq (equal)等于
-gt (greater than) 大于
-ge (greater equal) 大于等于
-ne (not equal) 不等于

文件权限判断

  • -r 有读的权限
  • -w 有写的权限
  • -x 有执行的权限

文件类型判断

  • -f 文件存在并且是一个常规文件
  • -e 文件存在
  • -d 文件存在并且是一个目录
# 判断23是否大于2
[linux@localhost datas]$ [ 23 -gt 2 ]
[linux@localhost datas]$ echo $?
0

# 判断helloworld.sh是否有写入权限
[linux@localhost datas]$ [ -w hellowrld.sh ]
[linux@localhost datas]$ echo $?
1

# 判断目录中文件是否存在
[linux@localhost datas]$ [ -e /home/linux/datas ]
[linux@localhost datas]$ echo $?
0

多条件判断

&& ||

[atguigu@hadoop101 ~]$ [ atguigu ] && echo OK || echo notOK
OK
[atguigu@hadoop101 shells]$ [ ] && echo OK || echo notOK
notOK

流程控制

IF判断

基本语法:

# 单分支
if [ 条件判断式 ];then
	程序
fi
#或者
if [ 条件判断式 ]
then
	程序
fi

# 多分支
if [ 条件判断式 ]
then
	程序
elif [ 条件判断式 ]
then
	程序
else
	程序
fi

注意事项:

​ ①[ 条件判断式 ],中括号和条件判断式之间必须有空格

​ ②if 后要有空格

实例:

[linux@localhost datas]$ cat if.sh
#!/bin/bash
if [ $1 -eq 1 ]
then
	echo "你好"
elif [ $1 -eq 2 ]
then
	echo "世界"
fi
[linux@localhost datas]$ bash if.sh 2
世界

case 语句

基本语法:

case $变量名 in
"值 1")
	如果变量的值等于值 1,则执行程序 1
;;
"值 2")
	如果变量的值等于值 2,则执行程序 2
;;
	…省略其他分支…
*)
	如果变量的值都不是以上的值,则执行此程序
;;
esac

注意事项:

(1)case 行尾必须为单词“in”,每一个模式匹配必须以右括号“)”结束。

(2)双分号“;;”表示命令序列结束,相当于 java 中的 break。

(3)最后的“*)”表示默认模式,相当于 java 中的 default。

[linux@localhost datas]$ cat case.sh
#!/bin/bash
case $1 in
1)
	echo "班长"
;;
2)
	echo "学习委员"
;;
3)
	echo "体育委员"
;;
esac
[linux@localhost datas]$ bash case.sh 2
学习委员

for循环

语法1

语法:

for (( 初始值;循环控制条件;变量变化 ))
do
	程序
done

实例:

[linux@localhost datas]$ cat for.sh
#!/bin/bash
s=0
for((i=1;i<=100;i++))
do
	s=$[$s+$i]	
done
echo $s
[linux@localhost datas]$ bash for.sh
5050

语法2

语法:

for 变量 in 值 1 值 2 值 3…
do
	程序
done

实例:

[linux@localhost datas]$ cat for2.sh
#!/bin/bash
for i in $*
do
	echo $i
done
[linux@localhost datas]$ bash for2.sh 1 2
1
2

(2)比较$*和$@区别

​ $*和$@都表示传递给函数或脚本的所有参数,不被双引号“”包含时,都以$1 $2 …$n 的形式输出所有参数。

[atguigu@hadoop101 shells]$ touch for3.sh
[atguigu@hadoop101 shells]$ vim for3.sh
#!/bin/bash
echo '=============$*============='
for i in $*
do
	echo "ban zhang love $i"
done

echo '=============$@============='
for j in $@
do
	echo "ban zhang love $j"
done

[atguigu@hadoop101 shells]$ chmod 777 for3.sh
[atguigu@hadoop101 shells]$ ./for3.sh cls mly wls
=============$*=============
banzhang love cls
banzhang love mly
banzhang love wls
=============$@=============
banzhang love cls
banzhang love mly
banzhang love wls

​ 当它们被双引号“”包含时,$*会将所有的参数作为一个整体,以“$1 $2 …$n”的形式输 出所有参数;$@会将各个参数分开,以“$1” “$2”…“$n”的形式输出所有参数。

[atguigu@hadoop101 shells]$ vim for4.sh
#!/bin/bash
echo '=============$*============='
for i in "$*"
#$*中的所有参数看成是一个整体,所以这个 for 循环只会循环一次
do
	echo "ban zhang love $i"
done

echo '=============$@============='
for j in "$@"
#$@中的每个参数都看成是独立的,所以“$@”中有几个参数,就会循环几次
do
	echo "ban zhang love $j"
done

[atguigu@hadoop101 shells]$ chmod 777 for4.sh
[atguigu@hadoop101 shells]$ ./for4.sh cls mly wls
=============$*=============
ban zhang love cls mly wls
=============$@=============
ban zhang love cls
ban zhang love mly
ban zhang love wls

WHILE循环

语法:

while [ 条件判断式 ]
do
	程序
done

实例:

[linux@localhost datas]$ cat while.sh
#!/bin/bash
s=0
i=1
while [ $i -le 100 ]
do
	s=$[$s + $i]
	i=$[$i + 1]
done
echo $s

[linux@localhost datas]$ bash while.sh
5050

read读取控制台输入

read (选项) (参数)

选项:

  • -p 指定读取值时的提示符
  • -t 指定读取值时等待的时间(秒)如果-t 不加表示一直等待

参数:

  • 变量:指定读取值的变量名
# 提示7秒内,读取控制台输入的名称
[atguigu@hadoop101 shells]$ touch read.sh
[atguigu@hadoop101 shells]$ vim read.sh
#!/bin/bash
read -t 7 -p "Enter your name in 7 seconds :" NN
echo $NN

[atguigu@hadoop101 shells]$ ./read.sh
Enter your name in 7 seconds : atguigu
atguigu

函数

系统函数

basename

​ basename [string / pathname] [suffix] (描述:basename命令会删掉所有的前缀包括最后一个‘/’字符,然后将字符串显示出来)
basename 可以理解为取路径里的文件名称

选项:

​ suffix为后缀,如果suffix被指定了,basename会将pathname或string中的suffix去掉

# 方式1
[linux@localhost datas]$ basename /home/linux/banzhang.txt
banzhang.txt

# 方式2
[linux@localhost datas]$ basename /home/linux/banzhang.txt .txt
banzhang

dirname

​ dirname 文件绝对路径 (描述:从给定的包含绝对路径的文件名中去除文件名(非目录的部分),然后返回剩下的路径(目录的部分))

​ dirname 可以理解为取文件路径的绝对路径名称

[linux@localhost datas]$ dirname /home/linux/banzhang.txt
/home/linux

自定义函数

# 格式
[ function ] funname[()]
{
	Action:
	[return int;]
}

# DESC 计算输入两个参数的值
[linux@localhost datas]$ cat sum.sh
#!/bin/bash
function sum(){
	s=0;
	s=$[$1 + $2]
	echo $s
}
read -p "input your param1:" P1
read -p "input your param2:" P2
sum $P1 $P2
[linux@localhost datas]$ bash sum.sh
input your param1:1
input your param2:2

正则表达式入门

​ 正则表达式使用单个字符串来描述、匹配一系列符合某个语法规则的字符串。在很多文 本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。在 Linux 中,grep, sed,awk 等文本处理工具都支持通过正则表达式进行模式匹配。

常规匹配

一串不包含特殊字符的正则表达式匹配它自己,例如:

[atguigu@hadoop101 shells]$ cat /etc/passwd | grep atguigu

就会匹配所有包含atguigu 的行

常用匹配

1)特殊字符:^

^匹配一行的开头,例如:

[atguigu@hadoop101 shells]$ cat /etc/passwd | grep a^

会匹配出所有以 a 开头的行

2)特殊字符:$

$ 匹配一行的结束,例如

[atguigu@hadoop101 shells]$ cat /etc/passwd | grep t$

会匹配出所有以t结尾的行

3)特殊字符:.

. 匹配一个任意的字符,例如

[atguigu@hadoop101 shells]$ cat /etc/passwd | grep r..t

会匹配包含rabt,rbbt,rxdt,root等的所有行,类似SQL中Like的_作用

4)特殊字符:*

* 不单独使用,他和上一个字符连用,表示匹配上一个字符 0 次或多次,例如

[atguigu@hadoop101 shells]$ cat /etc/passwd | grep ro*t

会匹配rt,rot,root,rooot,roooot等所有行

5)字符区间(中括号):[ ]

[ ] 表示匹配某个范围内的一个字符,例如

[6,8]------匹配 6 或者 8

[0-9]------匹配一个 0-9 的数字

[0-9]*------匹配任意长度的数字字符串 *

[a-z]------匹配一个 a-z 之间的字符

[a-z]* ------匹配任意长度的字母字符串

[a-c, e-f]-匹配 a-c 或者 e-f 之间的任意字符

[atguigu@hadoop101 shells]$ cat /etc/passwd | grep r[a,b,c]*t

会匹配 rt,rat, rbt, rabt, rbact,rabccbaaacbt 等等所有行

6)特殊字符:\

​ \ 表示转义,并不会单独使用。由于所有特殊字符都有其特定匹配模式,当我们想匹配 某一特殊字符本身时(例如,我想找出所有包含 '$' 的行),就会碰到困难。此时我们就要 将转义字符和特殊字符连用,来表示特殊字符本身,例如

[atguigu@hadoop101 shells]$ cat /etc/passwd | grep 'a\$b'

就会匹配所有包含 a$b 的行。注意需要使用单引号将表达式引起来。

shell工具

cut

cut命令从文件的每一行剪切字节,字符和字段并将这些字节,字符和字段输出
cut [选项参数] filename

默认分隔符时制表符

选项参数说明

  • -f 列号,提取第几列
  • -d 分隔符,按照指定分隔符分隔列,默认是制表符"\t"
  • -c 按字符进行切割 后加 n 表示取第几列 比如 -c 1
[linux@localhost datas]$ cat cut.txt
dong shen
guan zhen
wo wo
lai lai
le le
# DESC 切割cut.txt第一列
[linux@localhost datas]$ cut -d " " -f 1 cut.txt
dong
guan
wo
lai
le

# 切割 cut.txt 第二、三列
[atguigu@hadoop101 shells]$ cut -d " " -f 2,3 cut.txt
shen
zhen
wo
lai
le

# DESC 获取第三行第一个单词
[linux@localhost datas]$ cat cut.txt | grep guan | cut -d " " -f 1
guan

sed

sed是一种流编辑器,它一次处理一行内容,处理时,把当前处理的行存储在临时缓冲区中,成为“模式空间”,接着sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕,接着处理下一行,这样不断重复,知道文件末尾,文件内容并没有改变,除非你使用重定向存储输出
sed [选项参数] ‘command’ filename

  • -e 直接在指令列模式上进行sed的动作编辑

命令功能描述

  • a 新增
  • d 删除
  • s 查找并替换
# DESC 在第二行后增加mei nv字符
[linux@localhost datas]$ sed -e "2a mei nv" sed.txt
dong zhen
guan zhen
mei nv
wo wo
lai lai
1234567

awk

awk 一个强大文件分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理

awk [选项参数] 'pattern1 {action1} pattern2{action2}..' filename
1
  • -F 指定输入文件分隔符
  • -v 赋值一个用户定义变量

sort

sort 命令是在Linux里非常有用,它将文件进行排序,并将排序结果标准输出

sort [选项] (参数)
参数 描述
-n 依照数值大小排序
-t 以相反的顺序排序
-t 设置排序时使用的分隔字符
-k 指定需要排序的列

posted @   MrSponge  Views(44)  Comments(0Edit  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示