一篇文章Shell脚本快速入门

Shell脚本基础入门

Bash注释

Bash只支持单行注释,使用 #开头的都被当作注释语句:

整行注释
echo hello world # 行尾注释

通过Bash的一些特性,可以取巧实现多行注释:

: '
注释1
注释2
'

: <

但是,别闲的蛋疼去用取巧的多行注释,安心用 #来注释。

Bash基本数据类型

Bash中基本数据类型只有字符串类型,连数值类型都没有(declare -i可强制声明数值类型)。

比如:

都会当作字符串
echo haha
echo 1234

Bash字符串串联

Bash中字符串的串联操作,直接将两段数据连接在一起即可,不需要任何操作符。

例如:

echo "junma""jinlong"
echo 1234 5678

命令基本知识

变量赋值和引用变量

a=3
echo $a

a="www.junmajinlong.com"
echo $a

a='hello world'
echo $a

Shell中可以引用未定义的变量:

echo $xyzdefabc

可以定义空变量:

a=
echo $a

变量替换

变量替换是指在命令开始执行前,Shell会先将变量的值替换到引用变量的位置处。

例如:

a="hello"
echo $a world

在echo命令开始执行前,Shell会取得变量a的值hello,并将它替换到命令行的 $a处。于是,在echo命令开始执行时,命令行已经变成:

echo hello world

除了变量替换,Shell还会做其它替换:

  • 命令替换
  • 进程替换
  • 算术运算替换
  • 大括号扩展
  • 波浪号扩展
  • 路径扩展

这些扩展和替换,都是Shell在调用命令之前就完成的,这和其它语言解析代码的方式不一样。

学习Shell如何做命令行解析很重要,如果不掌握命令行解析,当遇到命令行语法错误后很可能会花掉大量无谓的时间去调试命令。而掌握命令行解析后,就会对命令生命周期了如执掌,不敢说一次就能写对所有命令行,但能节省大量调试时间,对写命令行和写脚本的能力也会上升一个层次。

命令替换

使用反引号或 $()可以执行命令替换。

cmd
$(cmd)

命令替换是指先执行cmd,将cmd的输出结果替换到 $()或反引号位置处。

例如:

echo id root
echo $(id root)

在echo命令执行前,会先执行id命令,id命令的执行结果:

$ id root
uid=0(root) gid=0(root) groups=0(root)

所以会将结果 uid=0(root) gid=0(root) groups=0(root)替换 $(id root)。于是,echo命令开始执行时,命令行已经变成了:

echo uid=0(root) gid=0(root) groups=0(root)

算术运算

$[]$(())或let命令可以做算术运算。

let是单独的命令,不能写在其它命令行中。

a=3
let a=a+1
echo $a

$[]$(())可以写在命令行内部,Shell在解析命令行的时候,会对它们做算术运算,然后将运算结果替换到命令行中。

a=33
echo $[a+3]
echo $((a+3))

因为变量替换先于算术替换,所以,使用变量名或引用变量的方式都可以:

a=333
echo $[$a+3]
echo $(($a+3))

退出状态码

每个命令执行后都会有对应的进程退出状态码,用来表示该进程是否是正常退出。

所以,在命令行中,在Shell脚本中,经常会使用特殊变量 $?判断最近一个前台命令是否正常退出。

通常情况下,如果 $?的值:

  • 为0,表示进程成功执行,即正常退出
  • 非0,表示进程未成功执行,即非正常退出
  • 但非0退出状态码并不一定表示错误,也可能是正常逻辑的退出

另外,在Shell脚本中,所有条件判断(比如if语句、while语句)都以0退出状态码表示True,以非0退出状态码为False。

exit命令

exit命令可用于退出当前Shell进程,比如退出当前Shell终端、退出Shell脚本,等等。

exit [N]

exit可指定退出状态码N,如果省略N,则默认退出状态码为0,即表示正确退出。

后台执行命令&

在命令的结尾使用 &符号,可以将这个命令放入后台执行。

命令放入后台后,会立即回到Shell进程,Shell进程会立即执行下一条命令(如果有)或退出。

使用 $!可以获取最近一个后台进程的PID。

sleep 20 &
echo $!

使用 wait命令可以等待后台进程(当前Shell进程的子进程)完成:

wait [n1 n2 n3 ...]

不给定任何参数时,会等待所有子进程(即所有后台进程)完成。

sleep 5 &
wait
echo haha

多命令组合

Shell中有多种组合多个命令的方式。

1.cmd1退出后,执行cmd2

cmd1;cmd2

2.cmd1正确退出(退出状态码为0)后,执行cmd2

cmd1 && cmd2

3.cmd1不正确退出后,执行cmd2

cmd1 || cmd2

4.逻辑结合: &&||可以随意结合

cmd1正确退出后执行cmd2,cmd2正确退出后执行cmd3
cmd1 && cmd2 && cmd3...

cmd1正确退出则执行cmd2,cmd1不正确退出会执行cmd3
cmd1正确退出,但cmd2不正确退出,也会执行cmd3
cmd1 && cmd2 || cmd3

cmd1正确退出会执行cmd3
cmd1不正确退出会执行cmd2,cmd2正确退出会执行cmd3
cmd1 || cmd2 && cmd3

5.将多个命令分组:小括号或大括号可以组合多个命令

小括号组合的多个命令是在子Shell中执行
即会先创建一个新的Shell进程,在执行里面的命令
(cmd1;cmd2;cmd3)

大括号组合的多个命令是在当前Shell中执行
大括号语法特殊,要求:
  1.开闭括号旁边都有空白,否则语法解析错误(解析成大括号扩展)
  2.写在同一行时,每个cmd后都要加分号结尾
  3.多个命令可分行书写,不要求分号结尾
{ cmd1;cmd2;cmd3; }
{
  cmd1
  cmd2
  cmd3
}

基本重定向

软件设计认为,程序应该有一个数据来源、数据出口和报告错误的地方。在Linux系统中,每个程序默认都会打开三个文件描述符(file descriptor,fd):

  • fd=0:标准输入,表示程序默认从哪里读取数据
  • fd=1:标准输出,表示程序默认将数据输出到哪里
  • fd=2:标准错误,表示程序默认将错误信息输出到哪里

文件描述符,说白了就是系统为了跟踪打开的文件而分配给它的一个数字,这个数字和文件有对应关系:从文件描述符读取数据,即表示从对应的文件中读取数据,向文件描述符写数据,即表示向对应文件中写入数据。

Linux中万物皆文件,文件描述符也是文件。默认:

  • fd=0的标准输入是/dev/stdin文件
  • fd=1的标准输出是/dev/stdout文件
  • fd=2的标准错误是/dev/stderr文件

这些文件默认又是各个终端的软链接文件:

$ ls -l /dev/std*
lrwxrwxrwx 1 root root 15 Jan  8 20:26 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 Jan  8 20:26 /dev/stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root root 15 Jan  8 20:26 /dev/stdout -> /proc/self/fd/1

$ ls -l /proc/self/fd/
lrwx------ 1 root root 64 Jan 16 10:40 0 -> /dev/pts/0
lrwx------ 1 root root 64 Jan 16 10:40 1 -> /dev/pts/0
lrwx------ 1 root root 64 Jan 16 10:40 2 -> /dev/pts/0
lr-x------ 1 root root 64 Jan 16 10:40 3 -> /proc/75220/fd

所以,默认情况下读写数据都是终端,例如:

数据输出到终端
$ echo haha
$ cat /etc/fstab

从终端读取数据
$ cat
hello   # 在终端输入
hello   # 在终端输出
world   # 在终端输入
world   # 在终端输出
^C

改变文件描述符对应的目标,可以改变数据的流向。比如标准输入fd=1默认流向是终端设备,若将其改为/tmp/a.log,便能让数据写入/tmp/a.log文件中而不再是终端设备中。

在Shell中,这种改变文件描述符目标的行为称为 重定向,即重新确定数据的流向。

其实,文件描述符有很多类操作,包括fd的重定向、fd的分配(open,即打开文件)、fd复制(duplicate)、fd的移动(move)、fd的关闭(close)。现在只介绍基础重定向操作。

Shell中,基础重定向操作有以下几种方式:

  • [n]>file:覆盖式输出重定向,输出到fd=n的数据改变流向输出到file文件中,file不存在则创建,file存在则先清空再写入数据
  • 省略n时 >file,等价于 1>file,即标准输出覆盖重定向到file文件中
  • [n]>>file:追加式输出重定向,输出到fd=n的数据改变流向输出到file文件的尾部,file不存在则创建,file存在则直接追加在文件尾部
  • 省略n时 >>file,等价于 1>>file,即标准输出追加重定向到file文件中
  • [n]<file< code>&#xFF1A;&#x8F93;&#x5165;&#x91CD;&#x5B9A;&#x5411;&#xFF0C;&#x4EE5;&#x8BFB;&#x53D6;&#x6A21;&#x5F0F;&#x6253;&#x5F00;file&#x6587;&#x4EF6;&#x5E76;&#x5206;&#x914D;fd=n&#xFF0C;file&#x4E0D;&#x5B58;&#x5728;&#x5219;&#x62A5;&#x9519;<ul><li>&#x7701;&#x7565;n&#x65F6;<code><file< code>&#xFF0C;&#x7B49;&#x4EF7;&#x4E8E;<code>0<file< code>&#xFF0C;&#x5373;&#x76F4;&#x63A5;&#x4ECE;file&#x4E2D;&#x8BFB;&#x6570;&#x636E;</file<></code></file<></code></li><li>&#x901A;&#x5E38;&#x7A0B;&#x5E8F;&#x90FD;&#x53EA;&#x4ECE;fd=0&#x4E2D;&#x8BFB;&#x6570;&#x636E;&#xFF0C;&#x6240;&#x4EE5;&#x5F53;n&#x4E0D;&#x7B49;&#x4E8E;0&#x65F6;&#xFF0C;&#x9700;&#x8981;&#x591A;&#x505A;&#x4E00;&#x6B65;&#x64CD;&#x4F5C;<code>3<file <&3< code>&#xFF0C;&#x770B;&#x4E0D;&#x61C2;&#x5148;&#x8DF3;&#x8FC7;</file></code></li></ul></file<>
  • &>file:这是特殊的重定向方式,表示将标准错误和标准输出都重定向到file文件中,等价于 >file 2>&1
  • &>>file:这是特殊的重定向方式,表示将标准错误和标准输出都追加到file文件中,等价于 >>file 2>&1

另外,经常用于输出的一个特殊目标文件是/dev/null,它是空设备,可以直接丢掉所有写入它的数据。

echo www.junmajinlong.com >/dev/null
curl -I www.junmajinlong.com 2>/dev/null >/tmp/a.log

cat

一个经常用的技巧是清空文件的方式:

$ cat /dev/null >file
$ >file

区分cat

Original: https://www.cnblogs.com/f-ck-need-u/p/12275851.html
Author: 骏马金龙
Title: 一篇文章Shell脚本快速入门

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/529494/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 实现邮箱发送验证码功能

    实现注册和忘记密码界面的邮箱发送验证码功能 邮箱验证步骤 本文使用了redis数据库做验证码的缓存,不想用redis数据库也可以直接将验证码放入mysql中,设置验证码有效期即可。…

    Linux 2023年6月7日
    0138
  • 【转】 一条 SQL 的执行过程详解

    MySQL 体系架构 – 连接池组件 1、负责与客户端的通信,是半双工模式,这就意味着某一固定时刻只能由客户端向服务器请求或者服务器向客户端发送数据,而不能同时进行。 …

    Linux 2023年6月13日
    0129
  • Linux账户,组,权限管理

    内容多数来源于https://wangchujiang.com/linux-command/c/chmod.html, 开源地址:https://github.com/jaywcj…

    Linux 2023年6月7日
    086
  • Linux内核驱动–硬件访问I/O【转】

    寄存器与内存 寄存器和内存之间有什么区别? [En] What is the difference between registers and memory? 寄存器和RAM的主要…

    Linux 2023年5月27日
    075
  • 3.20 什么是环境变量,Linux环境变量有哪些?

    变量是计算机系统用于保存可变值的数据类型,我们可以直接通过变量名称来提取到对应的变量值。在 Linux 系统中,环境变量是用来定义系统运行环境的一些参数,比如每个用户不同的家目录(…

    Linux 2023年6月7日
    0104
  • shell编程-杨辉三角简单实现

    shell编程-杨辉三角问题: 概述:中国古代数学家在数学的许多重要领域中处于遥遥领先的地位。中国古代数学史曾经有自己光辉灿烂的篇章,而杨辉三角的发现就是十分精彩的一页。杨辉三角形…

    Linux 2023年6月7日
    0110
  • mycat数据库集群系列之数据库多实例安装

    mycat 数据库集群系列之数据库多实例安装 最近在梳理数据库集群的相关操作,现在花点时间整理一下关于mysql数据库集群的操作总结,恰好你又在看这一块,供一份参考。本次系列终结大…

    Linux 2023年6月14日
    097
  • Linux 进程卡住了怎么办?

    在我们使用 Linux 系统时,如果网络或者磁盘等 I/O 出问题,会发现进程卡住了,即使用 kill -9 也无法杀掉进程,很多常用的调试工具,比如 strace, pstack…

    Linux 2023年5月27日
    088
  • HTML笔记整理–上节

    一、认识WEB 「网页」主要是由 &#x6587;&#x5B57;、 &#x56FE;&#x50CF;和 &#x8D85;&#x94…

    Linux 2023年6月13日
    097
  • typora使用

    一:typora、配置picgo+github安装以及配置 picgo 、Node.js和typora安装包见百度网盘链接: 参考的教程如下: 二:typora使用语法 Ctrl+…

    Linux 2023年6月13日
    090
  • 在Linux下安装Redis

    1. 下载Redis的压缩包 [root@spirit-of-fire ~]# wget http://download.redis.io/releases/redis-5.0.5…

    Linux 2023年6月14日
    098
  • Python的闭包是什么意思?

    闭包算是编程语言里一个比较常见的概念,但说实话,这个名词有点晦涩。在查看了半天网上的资料后,还是有点不明就里。 我疑惑的点主要是:这个东西是用来解决什么问题的?或者说,他的作用是什…

    Linux 2023年6月8日
    0106
  • Spring事务(一)-事务配置

    事务是数据库操作最基本的单元,是逻辑上的一组操作,这一组操作在同一个会话中要么都执行成功,要么都失败,这也是事务的最基本特性–原子性。事务的作用是为了保证系统数据的正确…

    Linux 2023年6月6日
    093
  • WPF 制作一个占用文件的测试工具

    我在开发软件进行测试时,需要测试拖入的文件被占用时软件的行为,于是就做了一个文件占用工具,此工具可以将某个文件进行占用,以及获取某个文件被哪个进程占用 先给大家看一下效果: 以上是…

    Linux 2023年6月6日
    0120
  • fork创建进程的步骤___Spring-boot-Starter启动器和其加载的过程___redis怎么监视正在执行的命令

    fork创建进程的步骤 我们都知道,在Linux中调用fork()函数,会创建一个子进程,那么在创建这个子进程的过程中,发生了些什么事情? 首先,我们要知道,fork()函数其实是…

    Linux 2023年5月28日
    0120
  • redis变慢查询

    Redis 通常是我们业务系统中一个重要的组件,比如:缓存、账号登录信息、排行榜等。 一旦 Redis 请求延迟增加,可能就会导致业务系统”雪崩”。 我在单…

    Linux 2023年5月28日
    0100
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球