Bash 的基本语法

警告
本文最后更新于 2023-11-09,文中内容可能已过时。

Bash 的基本语法

echo

由于后面的例子会大量用到echo命令,所以我们先简单了解一下echo命令

echo命令的作用是将接收到的参数原样输出

1
2
$ echo hello world
hello world

如果你想输入多行,可以用引号将参数包起来,这样,在你还未输入反引号时,换行不会直接执行命令,而是换行继续输入

1
2
3
4
5
$ echo "hello
> world
> " 
hello
world

-n参数

默认情况下,echo输出的文本末尾会有一个回车符。-n参数可以取消末尾的回车符,

1
2
3
$ echo hello world ; echo xiashuo.xyz
hello world 
xiashuo.xyz
1
2
$ echo -n hello world ; echo xiashuo.xyz
hello worldxiashuo.xyz

-e参数

-e参数会解释引号(双引号和单引号)里面的特殊字符(比如换行符\n)。如果不使用-e参数,即默认情况下,echo不解释它们,引号会让特殊字符变成普通字符,原样输出。

1
2
3
4
5
6
7
$ echo hello\nworld 
hellonworld
$ echo "hello\nworld" 
hello\nworld
$ echo -e "hello\nworld" 
hello
world

设置字体颜色

大部分时候,终端中的信息都是黑底白字,少数终端工具可能自带了配色方案,比如MobaXterm,会为特定的关键字设置颜色,但是大部分时候,shell 命令的输出的信息都是白色的,那我们没有办法控制文字的颜色呢,有,那就是ANSI escape codes

ANSI 转义序列是带内信令的标准,用于控制视频文本终端和终端模拟器上的光标位置、颜色、字体样式和其他选项。某些字节序列 (大多数以 ASCII 转义字符和方括号字符开头) 被嵌入到文本中。终端将这些序列解释为命令,而不是逐字显示的文本。

后面,我们在编写 shell 脚本地时候,我们希望在提示错误信息的时候,文本为红色,在进行警告信息提示的时候,文本为黄色,等等,甚至我们在做交互式地菜单的时候,我们可以给每个菜单项分配不同的颜色,方便区分,总之,echo 输出的信息带上颜色,可以让我们的 shell 脚本更加的生动。

关于 ANSI 转义序列可以做哪些事情,已经如何通过 ANSI 转义序列 结合 echo 命令设置文字颜色,请看《ANSI 转义码》

printf

printf 使用引用文本或空格分隔的参数,外面可以在 printf 中使用格式化字符串,还可以制定字符串的宽度、左右对齐方式等。默认的 printf 不会像 echo 自动添加换行符,我们可以手动添加\n

printf 命令的语法:

1
printf format-string [arguments...]

参数说明:

  • format-string: 为格式控制字符串
  • arguments: 为参数列表。

简单实践如下:

1
2
3
4
5
# 并不会主动换行
$ printf sdfs 112
sdfs$
$ printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234
郭靖     男      66.12

printf 的转义序列

序列 说明
\a 警告字符,通常为 ASCII 的 BEL 字符
\b 后退
\c 抑制(不显示)输出结果中任何结尾的换行字符(只在%b格式指示符控制下的参数字符串中有效),而且,任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符,都被忽略
\f 换页(formfeed)
\n 换行
\r 回车(Carriage return)
\t 水平制表符
\v 垂直制表符
\ 一个字面上的反斜杠字符
\ddd 表示 1 到 3 位数八进制值的字符。仅在格式字符串中有效
\0ddd 表示 1 到 3 位的八进制值字符

命令的格式

命令行环境中,主要通过使用 Shell 命令,进行各种操作。Shell 命令基本都是下面的格式。

1
$ command [ arg1 ... [ argN ]]

上面代码中,command是具体的命令或者一个可执行文件,shell 会在 PATH 环境变量中寻找此命令对应的可执行文件,如果未找到,则会报错

1
2
$ xiashuo
-bash: xiashuo: command not found

此时你需要指定命令对应的可执行文件的所在位置,通过绝对路径或者相对路径都可以,例如/path/2/executable/command arg1 arg2,或者,./folder/command arg1 arg2,我们在执行脚本的时候,就需要这样,不过为了方便,一般我们都会把可执行文件的所在目录添加到 PATH 环境变量中。

arg1 ... argN是传递给命令的参数,它们是可选的。Bash 使用空格(或 Tab 键)区分不同的参数。如果参数之间有多个空格,Bash 会自动忽略多余的空格。

1
$ ls -l

上面这个命令中,ls是命令,-l是参数。

有些参数是命令的配置项,这些配置项一般都以一个连词线开头,比如上面的-l。同一个配置项往往有长和短两种形式,比如-l是短形式,--list是长形式,它们的作用完全相同。短形式便于手动输入,长形式一般用在脚本之中,可读性更好,利于解释自身的含义。

有些参数不是命令的配置项,写了也不会有什么影响

1
2
3
4
5
# 短形式
$ ls -r

# 长形式
$ ls --reverse

上面命令中,-r是短形式,--reverse是长形式,作用完全一样。前者便于输入,后者便于理解。

命令的跨行

Bash 单个命令一般都是一行,用户按下回车键,就开始执行。有些命令比较长,写成多行会有利于阅读和编辑,这时可以在每一行的结尾加上反斜杠,Bash 就会将下一行跟当前行放在一起解释。

具体原理就是\将一行命令末尾的换行符\n转译为\\n,Bash 会将其当作长度为0的空字符处理,具体原理请看《转义和引号》的转义和反斜杠小节

1
2
3
4
5
$ echo foo bar

# 等同于
$ echo foo \
bar

分号(;)是命令的结束符,使得一行可以放置多个命令,上一个命令执行结束后,再执行第二个命令。

1
$ clear; ls

注意,使用分号时,第二个命令总是接着第一个命令执行,不管第一个命令执行成功或失败。我们可以将;理解为两个命令的无条件组合符

总结:

\可以讲一行命令拆成多行,;让我们可以将多个命令放在一行,

命令的有条件的组合

除了;,Bash 还提供两个命令组合符&&||,不过这两个符号是有条件的组合,后一个命令是否执行主要取决于第一个命令的执行结果。

这个跟 Java 中的熔断的概念很像

1
Command1 && Command2

如果Command1命令运行成功,则继续运行Command2命令。如果 Command1 失败的话,直接跳过 Command2

1
Command1 || Command2

如果Command1命令运行失败,则继续运行Command2命令。如果Command1命令运行成功,则跳过Command2

命令的执行结果是成功还是失败,可以根据命令的退出码来判断,命令的退出码可以通过$?变量获取,关于这个变量的细节,请看《Bash 变量》的特殊变量小节

如果有多层逻辑,还可以通过()来进行组合,比如

1
Command1 || (Command2 && Command3)

表示,如果Command1命令运行失败,则运行Command2命令。如果Command2命令运行成功,则继续运行Command3命令。如果 Command2 失败的话,直接跳过 Command3

一个经常使用的场景就是,在脚本中,我们经常需要切换到一个指定的目录,假设这个目录必须存在,那么如果这个目录不存在,我们就需要推出脚本,我们可以这样写

1
cd /path || exit

或者

1
cd /path || return

在子脚本中使用return的作用是退出父脚本对子脚本的调用,回到父脚本中,继续往后执行,但是不会终止 shell 进程,exit的作用是直接终止 shell 进程。

命令的类型

type命令用来判断命令的来源,是内置命令还是外部程序

1
2
3
4
5
6
7
8
$ type echo
echo is a shell builtin
$ type pwd
pwd is a shell builtin
$ type type
type is a shell builtin
$ type systemctl
systemctl is hashed (/usr/bin/systemctl)

type命令告诉我们,echo是内部命令,systemctl是外部程序(/bin/ls,对应着文件,就是外部程序),type命令本身也是内置命令。

使用type命令的-a参数,可以查看一个命令的所有定义:

1
2
3
4
5
6
7
$ type -a systemctl
systemctl is /usr/bin/systemctl
$ type -a echo
echo is a shell builtin
echo is /usr/bin/echo
$ type -a type
type is a shell builtin

我们发现echo命令既是内置命令,也有对应的外部程序。

使用type命令的-t参数,可以返回一个命令的类型:

  • 别名(alias)

  • 关键词(keyword)

  • 函数(function)

  • 内置命令(builtin)

  • 文件(file)。

1
2
3
4
5
6
7
8
$ type -t ls
alias
$ type -t systemctl
file
$ type -t if
keyword
$ type -t pwd
builtin

快捷键

Bash 提供很多快捷键,可以大大方便操作。下面是一些最常用的快捷键,完整的介绍参见《行操作》一章。

  • Ctrl + L:清除屏幕并将当前行移到页面顶部。效果类似于执行clear命令
  • Ctrl + C:中止当前正在执行的命令。
  • Shift + PageUp:向上滚动。
  • Shift + PageDown:向下滚动。
  • Ctrl + A:将光标移动到行头。
  • Ctrl + E:将光标移动到行尾。
  • Ctrl + U:从光标位置删除到行首。
  • Ctrl + K:从光标位置删除到行尾。
  • Ctrl + W:删除光标位置前一个单词。
  • Ctrl + D:关闭 Shell 会话。实际上为执行logout命令
  • :浏览已执行命令的历史记录。

除了上面的快捷键,Bash 还具有自动补全功能。命令输入到一半的时候,可以按下 Tab 键,Bash 会自动完成剩下的部分。比如,输入tou,然后按一下 Tab 键,Bash 会自动补上ch

除了命令的自动补全,Bash 还支持路径的自动补全。有时,需要输入很长的路径,这时只需要输入前面的部分,然后按下 Tab 键,就会自动补全后面的部分。如果有多个可能的选择,按两次 Tab 键,Bash 会显示所有选项,让你选择。

0%