Shell脚本入门指南

描述

一: 什么是 Shell

Shell 是一块包裹着系统核心的壳,处于操作系统的最外层,与用户直接对话,把用户的输入, 解释给操作系统,然后处理操作系统的输出结果,输出到屏幕给与用户看到结果。

Shell是用户与系统交互的主要方式之一。

操作系统

在这里插入图片描述
Shell的作用是

• 解释执行用户输入的命令或程序等

• 用户输入一条命令,Shell 就解释一条键盘输入命令,Linux 给与响应的方式,称之为交互式

操作系统

在这里插入图片描述

我们想要获取计算机的数据,不可能每次都编写程序,编译后,再运行,再得到我们想要的,例如你想找到一个文件,可以先写一段 C语言的代码,然后调用系统函数,通过 gcc 编译后,运行程序才能找到文件。

因此有大牛开发出了 Shell 解释器,能够让我们方便的使用 Linux,例如只要敲下 ls - lh 这样的字符串,Shell 解释器就会针对这句话翻译,解释成 ls-l -h 然后执行 ,通过终端输出结果,无论是图形化或是命令行界面。

即使我们用的图形化,点点点的动作,区别也只是

• 命令行操作,Shell 解释执行后,输出结果到黑屏命令行界面

• 图形化操作,Shell 接受点击动作,输出图案数据

常见的 Shell 类型

• Bash (Bourne Again Shell) :
最广泛使用的 Shell,是 GNU 项目的一部分,提供了丰富的功能和强大的脚本支持。
默认的 Shell 为大多数 Linux 发行版和 macOS(直到 macOS Mojave)。

• Sh (Bourne Shell) :
最早的 Unix Shell,是 Bash 的前身,功能相对简单。

• Tcsh (C Shell) :
提供了类似于 C 语言的语法,适合熟悉 C 语言的用户。

• Zsh (Z Shell) :
提供了许多高级功能,如自动补全、主题支持等,是 macOS Catalina 及以后版本的默认 Shell。

• Fish (Friendly Interactive Shell) :
一个现代的 Shell,强调用户友好性和交互性,提供了智能的自动补全和语法高亮等功能。

二: 什么是 Shell 脚本

当命令或者程序语句写在文件中,我们执行文件,读取其中的代码,这个程序文件就称之为 Shell 脚本

在 Shell 脚本里定义多条 Linux 命令以及循环控制语句,然后将这些 Linux 命令一次性执行完毕,执行脚本文件的方式称之为,非交互式方式,

• windows 中存在 *.bat 批处理脚本

• Linux 中常用 *.sh 脚本文件

Shell ==脚本语言属于一种弱类型语言==,无需声明变量类型,直接定义使用强类型语言,必须先定义变量类型,确定是数字、字符串等,之后再赋予同类型的值 centos7 系统中支持的 Shell 情况,有如下种类

 

# cat /etc/shells 
# /etc/shells: valid login shells
/bin/sh
/bin/bash
/usr/bin/bash
/bin/rbash
/usr/bin/rbash
/bin/dash
/usr/bin/dash
/usr/bin/tmux
/usr/bin/screen


 

Linux 默认 Shell

 

# echo $SHELL
/bin/bash

 

Shell 脚本规则

在 Linux 系统中,Shell 脚本或者称之为 (bash shell程序) 通常都是 vim 编辑,由 Linux 命令、bash shell 指令、逻辑控制语句和注释信息组成。

第一个 Shell 脚本

 

# vim test1.sh 
# cat test1.sh 

# 第一个 shell 脚本 这是注释
#!/bin/bash

echo "hello world!"

 

运行 Shell 脚本

 

# bash test1.sh 
hello world!

 

Shebang

计算机程序中 Shebang 指的是出现在文本文件的第一行前两个字符 #!

• 就是指明这个代码文件用哪个解释器去读

在 Unix 系统中,程序会分析 Shebang 后面的内容,作为解释器的指令,例如

• 以 #!/bin/bash 开头的文件,程序在执行的时候会调用 /bin/bash ,也就是 bash 解释器

• 以 #!/usr/bin/python 开头的文件,代表指定python解释器去执行

• 以 #!/usr/bin/env 解释器名称 ,是一种在不同平台上都能正确找到解释器的办法

注意事项:

• 如果脚本未指定 Shebang ,脚本执行的时候,默认用当前 shell 去解释脚本,即 $SHELL。

• 如果 Shebang 指定了可执行的解释器,如 /bin/bash /usr/bin/python ,脚本在执行时,文件名会作为参数传递给解释器

• 如果 #! 指定的解释程序没有可执行权限,则会报错“bad interpreter: Permission denied”。

• 如果 #! 指定的解释程序不是一个可执行文件,那么指定的解释程序会被忽略,转而交给当前的 SHELL 去执行这个脚本。

• 如果 #! 指定的解释程序不存在,那么会报错 “bad interpreter: No such file or directory”。

• #! 之后的解释程序,需要写其绝对路径 (如:#!/bin/bash),它是不会自动到 $PATH 中寻找解释器的。。

• 如果你使用 “bash test.sh” 这样的命令来执行脚本,那么 #! 这一行将会被忽略掉,解释器当然是用命令行中显式指定的 bash。

脚本的常用执行方式

第一种:采用 bash 或 sh + 脚本的相对路径或绝对路径(不用赋予脚本 +x 权限)

sh + 脚本的相对路径

 

$ sh helloworld.sh 
Helloworld

 

sh + 脚本的绝对路径

 

$ sh /home/zfox/datas/helloworld.sh 
helloworld

 

bash+脚本的相对路径

 

$ bash helloworld.sh 
Helloworld

 

bash + 脚本的绝对路径

 

$ bash /home/zfox/datas/helloworld.sh 
Helloworld

 

第二种:采用输入脚本的绝对路径或相对路径执行脚本(必须具有可执行权限 + x)

(a)首先要赋予 helloworld.sh 脚本的 + x权限

 

$ chmod 777 helloworld.sh

 

(b)执行脚本

相对路径(推荐使用)

 

$ ./helloworld.sh 
Helloworld

 

绝对路径

 

$ /home/zfox/datas/helloworld.sh 
Helloworld

 

注意:第一种执行方法,本质是 bash解析器 帮你执行脚本,所以脚本本身不需要执行权限。第二种执行方法,本质是脚本需要自己执行,所以需要执行权限

第二个 Shell 脚本:多命令处理

(1)需求: 在 /home/zfox/ 目录下创建一个 ljw.txt, 在 ljw.txt 文件中增加 I love ljw

(2)案例实操:

 

$ touch batch.sh
$ vim batch.sh

 

在 batch.sh 中输入如下内容

 

#!/bin/bash

cd /home/zfox
touch ljw.txt
echo "I love ljw"  ljw.txt

 

Shell 的优势

虽然有诸多脚本编程语言,但是对于 Linux 操作系统内部应用而言,Shell 是最好的工具,Linux 底层命令都支持 Shell 语句,以及结合三剑客 (grep、sed、awk) 进行高级用法。

• 擅长系统管理脚本开发,如软件启停脚本、监控报警脚本、日志分析脚本

每个语言都有自己擅长的地方,扬长避短,达到高效运维的目的是最合适的

三: Shell 中的变量

• 变量定义与赋值,注意变量与值之间不得有空格

 

name="zfox"

变量名
变量类型,bash默认把所有变量都认为是字符串

bash变量是弱类型,无需事先声明类型,是将声明和赋值同时进行

 

• 变量替换写弓|用

 

# name="zfox带你学bash"

# echo ${name}
zfox带你学bash

# echo $name    # 可以省略花括号
zfox带你学bash

 

• 变量名规则

• 名称定义要做到见名知意,切按照规则来,切不得引用保留关键字(help检查保留字)

• 只能包含数字、字母、下划线

• 不能以数字开头

• 不能用标点符号

• 变量名严格区分大小写

• 变量的作用域

• 本地变量。只针对当前的 shell 进程

系统变量

1)常用系统变量

HOME、PWD、SHELL、USER等

2)案例实操

(1)查看系统变量的值

 

$ echo $HOME
/home/zfox

 

(2)显示当前 Shell 中所有变量:set

 

$ set
BASH=/bin/bash
BASH_ALIASES=()
BASH_ARGC=()
BASH_ARGV=()

 

自定义变量

1.基本语法

(1)定义变量:变量=值

(2)撤销变量:unset 变量

(3)声明静态变量:readonly 变量,注意:不能unset

单引号 双引号区别

单引号变量,不识别特殊语法
双引号变量,能识别特殊符号
反引号,引用命令执行结果,等于 $() 用法

举例子:

 

# name="奥里给"
# echo ${name}
奥里给

# 单引号
# name2='${name}'
# echo $name2
${name}

# 双引号
# name2="${name}"
# echo $name2
奥里给

 

特殊变量

• $?

• 0 成功

• 1-255 错误码

Shell 的特殊变量,用在如脚本,函数传递参数使用,有如下特殊的,位置参数变量

 

$0        获取shel1脚本文件名,以及脚本路径
$n        获取shel1脚本的第n个参数,n在1~9之间,如$1,$2,$9,大于9则需要写,${10},参数空格隔开
$#        获取执行的she11脚本后面的参数总个数
$*        获取she11脚本所有参数,不加引号等同于 $@ 作用,加上引号 "$*" 作用是 接收所有参数为单个字符串,"$1 $2.
$@        不加引号,效果同上,加引号,是接收所有参数为独立字符串,如"$1" "$2" "$3”...,空格保留

 

特殊变量实践

 

#! bin/bash
# 注意单引号和双引号的区别
echo '特殊变量 $0 $1 $2 ... 的实践'
echo '结果: ' $0 $1 $2

echo '############################'
echo '特殊变量$# 获取参数个数的总数'
echo '结果: ' $#


echo '############################'
echo '特殊变量$* 实践'
echo '结果: ' $*

echo '############################'
echo '特殊变量 $@ 实践'
echo '结果: ' $@


#! /bin/bash

# $* 和 $@ 的区别
echo 'print each param from $*'
forvarin"$*"
do
    echo "$var"
done
echo 'print each param from $@'
forvarin"$@"
do
    echo "$var"
done


$*和$@的区别你了解吗?

$*和 $@ 都表示传递给函数或脚本的所有参数

当 $*和 $@ 不被双引号""包围时,它们之间没有任何区别,都是将接收到的每个参数看做一份数据,彼此之间以空格来分隔。
但是当它们被双引号""包含时,就会有区别了:

"$*"会将所有的参数从整体上看做一份数据,而不是把每个参数都看做一份数据。'yu chao 180 180 180 180"

"$@"仍然将每个参数都看作一份数据,彼此之间是独立的。
"chao'
"180"
"180"
"180"

比如传递了 5个参数,那么对于"$*"来说,这 5 个参数会合并到一起形成一份数据,它们之间是无法分割的;而对于"$@"来说,这5 个参数是相互独立的,它们是 5 份数据。

如果使用 echo 直接输出"$*"和"$@"做对比,是看不出区别的;但如果使用 for 循环来逐个输出数据,立即就能看出区别来。

 

Shell 变量面试题

问,如下输入什么内容

 

# cat test.sh
user1=`whoami`

# sh test.sh
# echo $user1

A.当前用户
B.zfox
c.空



答案选c


 

`linux命令`
在 linux 中反引号,中的命令执行结果会被保留下来

 

# name=`ls`
# echo $name
test1.sh test2.sh test3.sh


 

解答:

1. 每次调用 bash/sh 解释器执行脚本,都会开启一个子 shell,因此不保留当前的 shell 变量,通过 pstree 命令检查进程树

2. 调用 source 或者 点符号,在当前 shell 环境加载脚本,因此保留变量

环境变量设置

环境变量一般指的是用 export 内置命令导出的变量,用于定义 shell 的运行环境、保证 shell 命令的正确执行。

shell 通过环境变量确定登录的用户名、PATH路径、文件系统等各种应用。

环境变量可以在命令行中临时创建,但是用户退出shell终端,变量即丢失,如要永久生效,需要修改环境变量配置文件

• 用户个人配置文件 ~/.bash profile、 ~/.bashrc 远程登录用户特有文件

• 全局配置文件 /etc/profile/etc/bashrc,且系统建议最好创建在 /etc/profile.d/,而非直接修改主文件,修改全局配置文件,影响所有登录系统的用户

检查系统环境变量的命令

• set,输出所有变量,包括全局变量、局部变量

• env,当前用户的所有环境变量,包括全局环境变量和局部环境变量

• declare,输出所有的变量,如同 set

• export,显示和设置环境变量值

撤销环境变量

• unset 变量名,删除变量或函数

设置只读变量

• readonly,只有shell结束,只读变量失效

 

直接readonly 显示当前系统只读变量

# readonly name="超哥"
# name="chaochao"
-bash只读变量

 

环境变量初始化与加载顺序

操作系统

在这里插入图片描述

四: Shell 子串

bsah 一些基础的内置命令

 

echo
eval
exec
export
read
shift

 

echo 命令

 

-n 不换行输出
-e 解析字符串中的特殊符号


 换行

 回车
	 制表符 四个空格
 退格


# echo 你真胖;echo 你还挺可爱你真胖
你还挺可爱

# 不换行打印
# echo -n 你真胖;echo 你还挺可爱
你真胖你还挺可爱
# echo -n 你真胖;echo -n 你还挺可爱你真胖你还挺可爱 #

# echo -e "我看你挺
好的"
我看你挺
好的

# printf
printf "你好	我是	吴彦祖"
你好        我是        吴彦祖

 

eval

执行多个命令

 

# eval ls;cd /tmp
del_data.sh     hello.py     special_var.sh     t1.sh 
different.sh     hello.sh     nohup.out str1     test.txt

 

exec

不创建子进程,执行后续命令, 且执行完毕后,自动 exit

 

#  exec date
Fri 25 Apr 2025 08:56:41 AM CST

Connection closed.

Disconnected from remote host(Ubuntu-tencnt) at 0841.

 

Shell 子串的花式用法

 

${变量}                            返回变量值
${#变量}                            返回变量长度,字符长度
${变量:start}                    返回变量 offset 数值之后的字符
${变量length}                提取 offset 之后的 length 限制的字符
${变量#word}                        从变量开头删除最短匹配的 word 子串
${变量##word}                    从变量开头,删除最长匹配的 word
${变量%word}                        从变量结尾删除最短的 word
${变量%%word}                    从变量结尾开始删除最长匹配的 word
${变量/pattern/string}            用 string 代替第一个匹配的 pattern
${变量//pattern/string)            用 string 代替所有的 pattern
# name="yuchao180'

# echo $name
yuchao180
# echo ${name}
yuchao188

# echo ${#name}
9

# 截取子串的用法
# echo ${name:3}
hao180

# echo ${name:5}
o180
#设置起点,以及元素长度
# echo ${name4}
chao

 

• 多种统计长度的命令

 

# echo $name
yuchao180

# echo $name | wc -l
1
# echo $name |wc -L
9

# 解释wc命令参数用法 -l 行数   -L 最长一行的长度
# cat test1.txt | wc -l
3
# cat test1.txt | wc -L
8 

 

• 统计命令执行速度

字符串长度统计方式这么多,谁最快?
time 命令,统计命令执行时长
for 循环的 shell 编程知识语法

 

for number in {1..100}
do
    echo $number
done
写在一行的方法
for num in {1..100}; do echo $num; done
# 1.方法
# for n in {1..3}; do str1=`seg -s ":" 10`; echo $str1; done
1:2:3:4:5:6:7:8:9:10
1:2:3:4:5:6:7:8:9:10
1:2:3:4:5:6:7:8:9:10

# 结合 time 命令 ${#变量} 计算时间是13s
# time for n in {1..10000}; do char=`seq -s "chaoge" 100`; echo ${#char} &/dev/null; done
real  0m13.956s        实际运行的时间
user  0m6.005s        用户态执行的时间
sys   0m5.868s        内核态执行的时间

# 使用 wc -L 命令计算时间
# time for n in {1..10000}; do char=`seq -s "chaoge" 100`; echo ${char} | wc-L &/dev/null; done
real  0m49.262s        
user  0m18.843s        
sys   0m24.905s        

# expr命令的 length 函数统计
# time for n in {1..10000}; do char=`seq -s "chaoge" 100`; expr length "${char}" &/dev/null; done
real  0m28.511s        
user  0m11.960s        
sys   0m12.046s        

 

Shell 编程,尽量使用 linux 内置的命令,内置的操作,和内置的函数,C语言开发,效率最高,尽可能的减少管道符的操作

字符串截取

删除匹配到的子串

 

# name="I am chaoge"
# echo $name
I am chaoge

# echo ${name2}
am

# echo ${name5}
m cha

# name2="abcABC123ABcabc"

# #从开头匹配字符删除
# echo ${name2#a*c}
ABC123ABCabc

# echo ${name2##a*c}


# 利用%形式,从后向前匹配截取
# name2=abcABC123ABcabc

# echo ${name2%a*c}
abCABC123ABC

# echo ${name2%%a*c}

# echo ${name2%%a*C}
abcABC123ABCabc

# echo ${name2%a*C}
abcABC123ABCabc

 

替换字符串

 

# str1="Hello,man,i am your brother."
# echo $str1
Hello,man,i am your brother.


# echo ${str1/man/boy}
Hello,boy,i am your brother.


#多次匹配替换
# echo $str1
Hello,man,i am your brother.

# echo ${str1/o/0}
HellO,man,i am your brother.

# echo ${str1//o/O}
HellO,man,i am yOur brOther.

 

应用:批量修改文件名

创建一批文件

 

# touch chaochao_{1..5}_finished.jpg
# touch chaochao_{1..5}_finished.png

 

去掉剩下的所有 jpg 文件的 _finished 字符
编写 Shell 脚本如下:

 

#! /bin/bash

for file_name in `ls *fin*jpg`; do mv $file_name `echo ${file_name//_finished/}` ; done

 

特殊 Shell 扩展变量

 

如果parameter变量值为空,返回word字符串,赋值给result变量
result=${parameter:-word}

如果para变量为空,则word替代变量值,且返回其值
result=${parameter:=word}

如果para变量为空,word当作stderr输出,否则输出变量值
用于设置变量为空导致错误时,返回的错误信息
result=$fparameter:?word?

如果para变量为空,什么都不做,否则word返回
result=${parameter:+word}

 

链接:https://blog.csdn.net/weixin_50776420/article/details/147463567?spm=1001.2014.3001.5501

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分