跳转到内容

Bash基本语法

echo命令

echo命令用于在终端输出文本或变量的值。它是一个非常常用的命令,通常用于调试脚本或显示信息。作用是在屏幕输出一行文本,可以将该命令的参数原样输出。

Terminal window
echo hello world
hello world

如果想要输出的是多行文本,即包括换行符。这时需要把多文本放在引号里面。

Terminal window
echo "<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide"><img src="./image/sku-13811216-01.png"></div>
<div class="swiper-slide"><img src="./image/sku-13811216-02.png"></div>
<div class="swiper-slide"><img src="./image/sku-13811216-03.png"></div>
</div>
<div class="swiper-pagination"></div>
</div>"

上面的例子中,echo可以原样输出多行文本。

-n 参数

默认情况下,echo命令输出的文本末尾会有一个回车符号。-n参数可以取消末尾的回车符号,使得下一个提示符号紧跟在输出内容的后面。

Terminal window
echo -n hello world
hello world$
Terminal window
echo a;echo b
a
b
echo -n a;echo b
ab

例子中,-n参数可以让2个echo命令的输出连在一起,出现在同一行

-e 参数

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

Terminal window
echo "Hello\nWorld"
Hello\nWorld
# 双引号的情况
echo -e "Hello\nWorld"
Hello
World
# 单引号的情况
echo -e 'Hello\nWorld'
Hello
World

命令格式

命令行环境中,主要通过使用Shell命令。进行各种操作。Shell命令的格式如下:

Terminal window
command [ arg1 ... [ argN ]]

command是具体的命令或者一个可执行的文件,arg1 ... argN是传递给命令的参数,它们是可选的。

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

Terminal window
echo foo bar
# 等同于
echo foo \
bar

空格

Bash使用空格(或者Tab键)区分不同的参数

Terminal window
command foot bar

命令中的,foot和bar之间有一个空格,所以Bash认为它们是两个参数。 如果参数之间有多个空格,Bash会自动忽略多余的空格。

Terminal window
echo this is a test
this is a test

分号

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

Terminal window
clear;ls -l

例子中,Bash先执行clear命令,执行完成后,再执行ls -l命令。 注意,使用分号时,第二个命令总是接着第一个命令的执行,不管第一个命令执行是成功还是失败。

命令的组合符&&||

除了分号,Bash还提供了两个命令组合符号&&||,允许更好地控制多个命令之间的继发关系。

Command1 && Command2

上述命令的含义是,如果命令Command1执行成功,则继续执行Command2命令。

Command1 || Command2

上面命令的含义是,如果命令Command1命令运行失败,则继续运行Command2命令。

下面是一些例子:

Terminal window
cat text.txt; ls -l

只要cat命令执行结束,不管成功或者失败,都会继续执行ls -l命令

Terminal window
cat text.txt && ls -l

只要cat命令执行成功,才会继续执行ls -l命令,如果cat命令执行失败(比如不存在文件text.txt),那么ls命令就不会执行。

Terminal window
cat text.txt || ls -l

只有cat命令执行失败(比如不存在text.txt),才会继续执行ls -l命令,如果cat命令执行成功,ls命令就不会执行。

type命令

Bash本身内置了很多命令,同时也可以执行外部程序。怎么知道一个命令是内置命令还是外部程序呢?

type命令用来判断命令的来源

Terminal window
type echo
echo is a shell builtin
type ls
ls is hashed (/bin/ls)

上面代码中,type命令告诉我们,echo是内部命令,ls是外部程序(/bin/ls)

type命令本身也是内置的命令。 如果要查看一个命令的所有定义,可以使用type命令的-a参数

Terminal window
type -a echo
echo is a shell builtin
echo is /bin/echo

echo命令即是内置命令,也有对应的外部程序。

type命令的-t 参数,可以返回一个命令的类型:别名(alias),关键词(keyword),函数(function),内置命令(builtin)和文件(file)

Terminal window
type -t bash
file
type -t if
keyword

bash是文件,if是关键词。

快捷键

  • Ctrl + L:清除屏幕并将当前行移动到页面顶部
  • Ctrl + C:中止当前正在执行的命令
  • Shift + PageUp:向上滚动
  • Shift + PageDown:向下滚动
  • Ctrl + U:从光标位置删除到行首
  • Ctrl + K:从光标位置删除到行尾
  • Ctrl + W:删除光标位置前一个单词
  • Ctrl + D:关闭Shell会话

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

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

引号和转义

Bash只有一种数据类,就是字符串。不管用户输入什么数据,Bash都视为字符串。字符串相关的引号和转义,对Bash来说非常重要。

转义

某些特殊字符在Bash里面有特殊的含义,比如$&*\

Terminal window
echo $date

上面的echo输出$date不会有任何结果,因为$是一个特殊字符。如果想要原样输出这些字符,就必须在它们前面加上反斜杠,使其变成普通的字符。这就叫做转义。

Terminal window
echo \$date
$date

上述的命令中,只有在特殊字符$前面加上了反斜杠,Bash才会将其视为普通字符。输出结果是$date。 反斜杠本身也是特殊字符,如果想要原样输出反斜杠,就需要对其自身转义,连续使用两个反斜杠即可。(\\)

Terminal window
echo \\

反斜杠除了用于转义,还可以表示一些不可打印的字符.

  • \a
  • \b: 退格
  • \n: 换行
  • \r: 回车
  • \t: 制表符

如果想要在这些命令行中使用这些不可打印的字符,可以把它们放到引号里面,然后使用echo命令的-e参数.

Terminal window
echo a\tb
alt
echo -e "a\tb"
a b

上述例子中,命令行直接输出不可打印字符\t,Bash不能正常解释.必须把它们放在引号之中,然后使用echo命令的-e参数.

换行符是一个特殊的字符,表示命令的结束,Bash收到这个字符后,就会对其输入的命令进行解释执行.换行符前面加上反斜杠转义,就使得换行符变成普通字符,Bash会将其当做长度为0的空字符处理,从而可以将一行命令写成多行.

Terminal window
mv \
/path/to/foo \
/path/to/bar
# 等同于
mv /path/to/foo /path/to/bar

例子中,如果一条命令过长,就可以在行尾使用反斜杠,将其改写成多行.这是常见的多行命令的写法.

单引号

Bash允许字符串放在单引号或双引号之中,加以引用. 单引号用于保留字符的字面含义,比如各种特殊字符在单引号里,都会变成普通字符.比如* $ \等。

Terminal window
echo '*'
*
echo '$((2+2))'
$((2+2))
echo '$(echo foo)'
$(echo foo)

上面命令中,单引号使得 Bash 扩展、变量引用、算术运算和子命令,都失效了。如果不使用单引号,它们都会被 Bash 自动扩展。

由于反斜杠在单引号里面变成了普通字符,所以如果单引号之中,还要使用单引号,不能使用转义。合理的方法是在双引号中使用单引号

Terminal window
echo "it's a test"

双引号

双引号比单引号更宽松,大部分特殊字符在双引号里面都会失去特殊的含义,变成普通字符。

Terminal window
echo "*"
*

通配符*是一个特殊字符,放在双引号之中,就变成了普通字符,会原样输出。这一点需要特别留意,这意味着双引号里面不会进行文件名扩展。 但是,$ 反引号` 和反斜杠\ 这三个字符在双引号之中,依然有特殊含义,会被Bash自动扩展。

Terminal window
echo "$SHELL"
/bin/zsh
echo "`date`"
Sat Apr 12 11:41:11 CST 2025echo "`date`"

例子中,$ 和反引号` 在栓引号中,都保持特殊含义。$符号用来引用变量,反引号则执行子命令。

Terminal window
echo "I'd say: \"hello.\""
I'd say: "hello."
echo "\\"
\

反斜杠在双引号之中保持特殊含义用来转义。索引可以使用反斜杠,在双引号之中插入双引号或者插入反斜杠本身。

换行符在双引号之中会失去特殊含义,Bash不在将其解释为命令的结束,只是作为普通的换行符。所以可以利用双引号,在命令输入多行文本。

Terminal window
echo "hello
> world"
hello
world

Bash在正常情况下会将换行符解释为命令的结束,但是换行符在双引号之中就失去了特殊作用,只用来换行,所以可以输入多行文本。echo命令会将换行符原样输出,显示的时候正常解释为换行。

双引号的另一个常见的使用场景是文件名包含空格。这时候就必须使用双引号或(单引号),将文件名放在里面。

Terminal window
ls "tow words.txt"

tow words.txt是一个包含空格的文件名,如果不放在双引号里面,就会被Bash当做两个文件。

双引号会原样保存多余的空格。

Terminal window
echo "this is a test"
this is a test

双引号还有一个作用,就是保存原始命令的输出格式。

Terminal window
echo $(cal)
April 2025 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
echo "$(cal)"
April 2025
Su Mo Tu We Th Fr Sa
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30

如果$(cal)不放在双引号之中,echo 就会将所有结果以单行输出。丢弃了所有原有的格式。

Here文档

Here文档是一种输入多行字符串的方法,格式如下:

Terminal window
<< EOF
text
EOF

它的格式分成开始标记<< EOF 和结束标记 EOF。开始标记是两个小于号 + Here 文档的名称,名称可以随意取,后面必须是一个换行符;结束标记是单独一行顶格写的Here文档名称,如果不是顶格,结束标记不起作用。两者之间就是多行字符串的内容。

Terminal window
cat << EOF
> <html>
> <head>
> <title>
> The title of your page
> </title>
> </head>
>
> <body>
> Your page content goes here.
> </body>
> </html>
> EOF
<html>
<head>
<title>
The title of your page
</title>
</head>
<body>
Your page content goes here.
</body>
</html>

Here文档内部会发生变量替换,同时支持反斜杠转义,但是部支持通配符扩展,双引号和单引号也失去语法作用,变成了普通字符。

Terminal window
cat << EOF
> $foo
> "$foo"
> '$foo'
> EOF
hello world
"hello world"
'hello world'

变量$foo发生了替换,但是双引号和单引号都原样输出了。表明它们已经失去了引用的功能。

如果不希望发生变量替换,可以把Here文档的开始标记放在单引号之中。

Terminal window
cat << 'EOF'
> $foo
> "$foo"
> '$foo'
> EOF
$foo
"$foo"
'$foo'

上面的例子中,Here文档的开始标记EOF放在单引号之中,导致变量替换失效了。 Here文档的本质是重定向,它将字符串重定向输出给某个命令,相当于包含了echo命令。

Terminal window
command << EOF
> string
> EOF
# 等同于
echo string | command

此外,Here文档也不能作为变量的值,只能用于命令的参数。

Here字符串

Here文档还有一个变体,叫Here字符串(Here string),使用三个小于号<<<表示。

Terminal window
<<< string

它的作用是将字符串通过标准输入,传递给命令。

有些命令直接接受给定的参数,与通过标准输入接受参数,结果是不一样的。所以才有了这个语法,使得将字符串通过标准输入传递命令更方便,比如cat命令只接受标准输入传入的字符串。

Terminal window
cat <<< 'hi there'
hi there
# 等同于
echo 'hi there' | cat

上面的第一种语法使用了Here字符串,要比第二种语法抗上去语义更好,也更简洁。

Terminal window
md5sum <<< 'ddd'
# 等同于
echo 'ddd' | md5sum

上面例子中,md5sum命令只能接受标准输入作为参数,不能直接将字符串放在命令后面,会被当作文件名。即:md5sum ddd里面的ddd会被解释成文件名。这时就可以用Here字符串,将字符串传给md5sum命令。