前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >3小时精通shell脚本

3小时精通shell脚本

作者头像
用户10127530
发布2022-10-26 17:31:11
5020
发布2022-10-26 17:31:11
举报
文章被收录于专栏:半旧的技术栈

3小时精通shell脚本

1 shell简介

1.1 shell是什么

linux操作系统包含内核kernel,人机交互程序与应用,其中shell就属于人机交互程序。

当我们在linux终端输入一个命令时,shell会把他先转换为内核可以理解的命令,有内核执行并将执行结果返回到终端。shell在这里扮演的角色就是翻译。

同时shell也是一种编程语言。shell有很多版本,目前linux默认装载的是Bash Shell

查看当前系统应用的shell

代码语言:javascript
复制
wangzhou@wangzhou-Latitude-5410:~$ echo $SHELL
/bin/bash

临时切换shell

代码语言:javascript
复制
wangzhou@wangzhou-Latitude-5410:~$ tcsh
wangzhou-Latitude-5410:~> 

查看当前系统支持哪些版本shell。

代码语言:javascript
复制
wangzhou@wangzhou-Latitude-5410:~$ 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
/bin/tcsh
/usr/bin/tcsh

1.2 环境变量

前面提到shell相当于一个翻译官,那么shell是怎么找到要执行的命令(执行命令其实是执行脚本程序)的应用的位置呢?答案是通过环境变量。使用如下命令查看当前用户环境变量(不同用户有不同的环境变量)。

代码语言:javascript
复制
wangzhou@wangzhou-Latitude-5410:~$ echo $PATH
/home/wangzhou/Applications/node-v16.4.1-linux-x64/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/usr/local/sbin/platform-tools/

增加环境变量。 法1:export命令。这种方法是临时修改,只对当前窗口有效,重新打开一个新窗口就失效了。注意一定要加$PATH,这表示追加环境变量,否则你的其它环境变量就没有了。

代码语言:javascript
复制
 export PATH=$PATH:/HOME/ct

法2:可以通过修改文件来实现,这种方式是非临时修改。根目录下使用ls -a可以看到.bashrc(个人环境变量),.bash_profile(个人用户环境变量),这两个文件都可以实现相同的功能,只不过前者是每打开一个新的窗口都会被加载一次,而后者在切换用户时加载一次。在/etc/profile/etc/bashrc两个文件中修改环境变量则是系统级别,所有用户都会生效。

2.shell编程

2.1 文档命令

shell命令有19种,只要是linux的命令都可以被称shell命令。如此多的命令我们肯定记不住,我们着重讲解文档命令,这样不懂的命令使用文档命令就可以看到命令的详细介绍。

我们最常用的文档命令就是man.下面应用他查下ls的用法。

代码语言:javascript
复制
man ls

效果如下。

2.2 管道服务

符号|表示管道。

代码语言:javascript
复制
wangzhou@wangzhou-Latitude-5410:~$ ls -a
.         anriodagent    .bashrc  Documents   .gradle       .local    .mysql_history      .npmrc             platform-tools   runoob      .ssh_bak                   .viminfo    图片
..        Applications   .cache   Downloads   IdeaProject   logs      .nbprofiler         .oracle_jre_usage  .profile         snap        .sudo_as_admin_successful  .visualvm   桌面
adb       .arthas        .config  .gitconfig  IdeaProjects  .m2       nodedev             .pam_environment   Public           soft        Templates                  .vscode
a.jpg     .bash_history  Desktop  .gnupg      .java         .mozilla  .node_repl_history  Pictures           .python_history  springdemo  .thunderbird               .wget-hsts
.android  .bash_logout   dev      .gphoto     learngit      Music     .npm                .pki               .rpmdb           .ssh        Videos                     下载
wangzhou@wangzhou-Latitude-5410:~$ ls -a | grep .bash
.bash_history
.bash_logout
.bashrc

上面ls -a | grep .bash会先执行ls -a,然后把执行结果传递给管道,管道再传给grep .bash执行过滤。可以多次使用管道。

2.3 输入输出

(1) <> <,>表示输入、输出符号。它主要有两个作用:重定向和输入输出。先理解下重定向。

linux所有的文件、目录都有一个文件描述符作为唯一标识。我们可以使用文件描述符来访问linux操作系统的所有文件、目录。后面我们也会体会到这种机制的好处。

首先将之前ls -a查询到的内容保存在文件1.txt中,然后使用exec 3< 1.txt将文件1.txt标识为3,类型是标准输入。现在执行grep .bash <&3,效果如下。

可以看到,标准输入指的是将3所指代的内容输入到目标文件/命令,而标准输出则是从目标文件/命令输出到标识3所指代文件,输入输出是相对于目标而言的。

注意:0(STDIN),1(STDOUT),2(STDERR)是系统自带的标识,请不要使用。

其实上面重定向已经包含了输入输出的作用了,下面单独使用他的输入、输出功能,将ls -a的内容从1.txt输出。

代码语言:javascript
复制
wangzhou@wangzhou-Latitude-5410:~$ ls -a > 1.txt
wangzhou@wangzhou-Latitude-5410:~$ cat 1.txt 

(2)>><< >><<<>作用类似,不过是追加模式,使用方式如下。

代码语言:javascript
复制
wangzhou@wangzhou-Latitude-5410:~$ cat << END
> 123
> 234
> END
123
234

(3) read 使用read可以通过键盘按行定义变量。

代码语言:javascript
复制
wangzhou@wangzhou-Latitude-5410:~$ read a
/Desktop
wangzhou@wangzhou-Latitude-5410:~$ ls -a `echo $a`
.  ..

2.4 shell脚本

2.4.1 hello,world

为实现某个任务,将多个shell命令组合成可执行文件就是shell脚本。shell脚本用文档编辑器就可以编写,给予可执行权限就可以执行。

新建a.sh

代码语言:javascript
复制
#!/bin/bash
# This is a test scrpit.
# time:2021-11-19
# autor:z
# motification time:
# motifycation author:
echo "hello,world!"
exit 0

#表示注解,其作用是解释脚本功能,记录脚本的创建、修改时间、作者等。

#!/bin/bash指定了该shell脚本的解析器,建议文件后缀与解析器的指定匹配,比如.sh就对应bash解析器。

指定执行权限。+x参数表示给所有用户赋予执行权限,u+x则表示给当前用户赋予权限。

代码语言:javascript
复制
chmod +x a.sh

执行结果如下。

代码语言:javascript
复制
wangzhou@wangzhou-Latitude-5410:~$ ./a.sh
hello,world!

另外,将a.sh的路径加到环境变量中,就可以像其它普通的shell命令一样执行他了。

2.4.2 定义变量

使用set命令可以查看已经被linux系统占用的变量(相当于java的保留字),由于个数太多,我们筛选了少部分看即可。

代码语言:javascript
复制
set | grep -e HOME -e BASH

在b.sh中随便打个系统变量看看。

代码语言:javascript
复制
echo "hello,world!"
echo "\$0":$0
exit 0

执行结果如下。

代码语言:javascript
复制
wangzhou@wangzhou-Latitude-5410:~$ ./a.sh
hello,world!
$0:./a.sh

其它常用的shell系统变量参考下表。

自己定义变量很简单,有字母、数字、下划线组成。局部变量和全局变量定义示范如下。

代码语言:javascript
复制
#!/bin/bash
var=10
function getvar(){
local var1=1
echo "var1:$var1"
echo "var:$var"
}
getvar

执行结果如下。

代码语言:javascript
复制
wangzhou@wangzhou-Latitude-5410:~$ ./b.sh 
var1:1
var:10
2.4.3 数组

参考下列代码,值的注意的是,shell中数组长度可变。

代码语言:javascript
复制
wangzhou@wangzhou-Latitude-5410:~$ ARRAY=(1 2 4)
wangzhou@wangzhou-Latitude-5410:~$ echo $ARRAY
1
wangzhou@wangzhou-Latitude-5410:~$ echo ${ARRAY[0]}
1
wangzhou@wangzhou-Latitude-5410:~$ echo ${ARRAY[@]}
1 2 4
wangzhou@wangzhou-Latitude-5410:~$ echo ${ARRAY[@]:1}
2 4
wangzhou@wangzhou-Latitude-5410:~$ ARRAY[3]=7
wangzhou@wangzhou-Latitude-5410:~$ echo ${ARRAY[@]:1}
2 4 7
2.4.4 运算符

如下表。

我们使用let来进行运算。下面示例如下。

代码语言:javascript
复制
wangzhou@wangzhou-Latitude-5410:~$ let var=11%2
wangzhou@wangzhou-Latitude-5410:~$ echo $var
1
2.4.5 进制转换

八进制以0开头,0x十六进制。

代码语言:javascript
复制
wangzhou@wangzhou-Latitude-5410:~$ let var=011
wangzhou@wangzhou-Latitude-5410:~$ echo $var
9

可以自定义进制,比如二进制。

代码语言:javascript
复制
wangzhou@wangzhou-Latitude-5410:~$ let var=2#111
wangzhou@wangzhou-Latitude-5410:~$ echo $var
7
2.4.6 条件判断

下面代码在实际shell编程中常用于脚本连接:下一个shell脚本常常依赖于上一个脚本,我们先依次检查每一个脚本,避免前面脚本的错误影响后面脚本的结果。

代码语言:javascript
复制
vim d.sh
#!/bin/bash
ls $1
if[$? -eq 0];then
  echo "The last exit code is 0"
else
  echo "The last exit code is not 0"
  exit 1
 fi

执行 ./d.sh a.sh则输出"The last exit code is 0",执行./d.sh e.sh则输出“The last exit code not 0",这是因为e.sh都还没有创建呢。

条件判断的格式还有扩展写法。

代码语言:javascript
复制
if [ command ];then
     符合该条件执行的语句
elif [ command ];then
     符合该条件执行的语句
else
     符合该条件执行的语句
fi

常用的一些类型的判断有默认方法,这些方法常常结合上面的if语句使用,十分方便。

代码语言:javascript
复制
[ -a FILE ] 如果 FILE 存在则为真。
[ -d FILE ] 如果 FILE 存在且是一个目录则返回为真。
[ -e FILE ] 如果 指定的文件或目录存在时返回为真。
[ -f FILE ] 如果 FILE 存在且是一个普通文件则返回为真。
[ -r FILE ] 如果 FILE 存在且是可读的则返回为真。
[ -w FILE ] 如果 FILE 存在且是可写的则返回为真。(一个目录为了它的内容被访问必然是可执行的)
[ -x FILE ] 如果 FILE 存在且是可执行的则返回为真。
[ -z STRING ] 如果STRING的长度为零则返回为真,即空是真
[ -n STRING ] 如果STRING的长度非零则返回为真,即非空是真
[ STRING1 ]  如果字符串不为空则返回为真,与-n类似
[ STRING1 == STRING2 ] 如果两个字符串相同则返回为真
[ STRING1 != STRING2 ] 如果字符串不相同则返回为真
[ STRING1 < STRING2 ] 如果 “STRING1”字典排序在“STRING2”前面则返回为真。
[ STRING1 > STRING2 ] 如果 “STRING1”字典排序在“STRING2”后面则返回为真。
[ INT1 -eq INT2 ] INT1和INT2两数相等返回为真 ,=
[ INT1 -ne INT2 ] INT1和INT2两数不等返回为真 ,<>
[ INT1 -gt INT2 ] INT1大于INT2返回为真 ,>
[ INT1 -ge INT2 ] INT1大于等于INT2返回为真,>=
[ INT1 -lt INT2 ] INT1小于INT2返回为真 ,<
[ INT1 -le INT2 ] INT1小于等于INT2返回为真,<=
[ ! EXPR ] 逻辑非,如果 EXPR 是false则返回为真。
[ EXPR1 -a EXPR2 ] 逻辑与,如果 EXPR1 and EXPR2 全真则返回为真。
[ EXPR1 -o EXPR2 ] 逻辑或,如果 EXPR1 或者 EXPR2 为真则返回为真。
[ ] || [ ] 用OR来合并两个条件
[ ] && [ ] 用AND来合并两个条件
2.4.7 循环语句

for循环。

代码语言:javascript
复制
for 变量 in 串行
do
   执行命令
done

while循环:当条件满足时执行。

代码语言:javascript
复制
while 条件测试
do
   执行命令
done

util循环:直到满足条件停止。

代码语言:javascript
复制
until 条件测试
do
  执行命令
done

使用break关键字可以跳出循环,而且还可以跳出嵌套循环,下面给出了示例代码,特别注意空格与示例一致,不加空格的后果您感兴趣可以尝试。

代码语言:javascript
复制
$ cat test1.sh
#!/bin/bash
i=1
while true
do
        if [ $i -gt 3 ] #没有空格则报错
        then
                break
        fi
        echo "i="$i
        sleep 1
        i=`expr $i + 1` # 有空格是数字运算,没有空格是字符串拼接
done

执行结果如下。

代码语言:javascript
复制
24724@LAPTOP-OCSC7S98 MINGW64 ~
$ ./test1.sh
i=1
i=2
i=3

下面示例break 2跳出双层循环。

代码语言:javascript
复制
#!/bin/bash
i=1
j=1
while true
do
        while true
        do
                if [ $i -gt 3 ]
                then
                break 2
        fi
        echo "i="$i
        echo "j="$j
        sleep 1
        i=`expr $i + 1`
        done
j=`expr $i + $j`
echo "j="$j
done

执行结果如下,说明在跳出内存循环时也跳出了第二层外层循环。

代码语言:javascript
复制
24724@LAPTOP-OCSC7S98 MINGW64 ~
$ ./test1.sh
i=1
j=1
i=2
j=1
i=3
j=1

关键字continue可以跳出当层循环,这里不再赘述。

2.4.8 用户交互

最简单的交互。使用read实现用户交互,让用户输入密码。

代码语言:javascript
复制
echo -e "请输入密码: \c"
pwdstr=''
while : ;
do
    read -n 1 -s -p "" pw
    if [ $pw ]; then
        pwdstr=${pwdstr}$pw
        echo -e "*\c" 
    else
        echo
        break
    fi
done
 
echo "password is :$pwdstr"

执行结果如下。

代码语言:javascript
复制
$ ./test2.sh
password is :echo -e 请输入密码: \c
******
password is :123455

第二种方式是通过菜单选择来实现交互。

代码语言:javascript
复制
function menu ()
#!/bin/bash
select i in a b c d
do
	case $i in 
		a)
			ls
			;;
		b)
			pwd
			;;
		c)
			w
			;;
		d)
			uname -a
			;;
		*) 
			echo "Please input 1-4"
			;;
	esac
done 

效果如下。

代码语言:javascript
复制
$ ./test2.sh
1) a
2) b
3) c
4) d
#? a
Please input 1-4
#? 1
 「开始」菜单                Contacts    git.ignore             'My Documents'     NTUSER.DAT{53b39e88-18c4-11ea-a811-000d3aa4692b}.TM.blf                                        Pictures       SendTo
'3D Objects'                 Cookies     IntelGraphicsProfiles   NetHood           NTUSER.DAT{53b39e88-18c4-11ea-a811-000d3aa4692b}.TMContainer00000000000000000001.regtrans-ms   PrintHood      Templates
 AppData                     Desktop     Links                   NTUSER.DAT        NTUSER.DAT{53b39e88-18c4-11ea-a811-000d3aa4692b}.TMContainer00000000000000000002.regtrans-ms   Recent         test1.sh
'Application Data'           Documents  'Local Settings'         ntuser.dat.LOG1   ntuser.ini                                                                                    'Saved Games'   test2.sh
 BullseyeCoverageError.txt   Downloads   Music                   ntuser.dat.LOG2   OneDrive                                                                                       Searches       Videos
#? 2
/c/Users/24724
2.4.9 文本批量处理

grep过滤,sed批量行处理,awk批量列处理。号称文本处理三剑客,特别常用。这里仅仅抛砖引玉,读者需要使用他们进行文本处理时可以参考博客:https://www.cnblogs.com/along21/p/10366886.html.

2.4.10 调试
  • 在命令行提供参数:$sh -x script.sh-
  • .脚本开头提供参数:#!/bin/sh -x
  • 在脚本中用set命令启用or禁用参数:其中set -x表示启用,set +x表示禁用。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-11-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 3小时精通shell脚本
  • 1 shell简介
    • 1.1 shell是什么
      • 1.2 环境变量
      • 2.shell编程
        • 2.1 文档命令
          • 2.2 管道服务
            • 2.3 输入输出
              • 2.4 shell脚本
                • 2.4.1 hello,world
                • 2.4.2 定义变量
                • 2.4.3 数组
                • 2.4.4 运算符
                • 2.4.5 进制转换
                • 2.4.6 条件判断
                • 2.4.7 循环语句
                • 2.4.8 用户交互
                • 2.4.9 文本批量处理
                • 2.4.10 调试
            相关产品与服务
            腾讯云小微
            腾讯云小微,是一套腾讯云的智能服务系统,也是一个智能服务开放平台,接入小微的硬件可以快速具备听觉和视觉感知能力,帮助智能硬件厂商实现语音人机互动和音视频服务能力。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档