Bash语法(各种奇怪符号)

Last Updated: 2023-06-01 09:23:38 Thursday

-- TOC --

在Bash命令行中,常常见到各种奇奇怪怪的符号,比如分号[;],&&,|,||,>,<,>>,<<,<<<,冒号[:],&,~和~+,|&,有些头大,本文尽量总结。

这些符号及其功能是Bash提供的,命令程序并不知道这些符号的存在;因此,给命令行的输入,在Bash中执行与不在Bash中执行,有些是不一样的。

分号[;]

分号的作用,就是简单的将多个命令分开,并列开来,就像C语言或Python中的多条语句写在了同一行,需要用分号来隔开。

$ echo 1; echo 2; echo 3
1
2
3
$ clear; ls
...

但我发现,有的时候也会执行失败,也许这种用法有些怪异吧:

$ alias kk='echo cs.pynote.net'; kk; unalias kk;
kk: command not found

分号[;]是命令的结束符,使得一行可以放置多个命令,上一个命令执行结束后,再执行第二个命令。使用分号时,第二个命令总是接着第一个命令执行,不管第一个命令执行成功或失败

分号在Bash脚本中也有作用,它同样表示一个命令的结束:

$ if true; then echo cs.pynote.net; fi
cs.pynote.net
$ if false; then echo cs.pynote.net; fi

true和false

两个特殊的极其简单的命令:

$ true
$ echo $?
0
$ false
$ echo $?
1

与一般编程语言中的TRUE和FALSE的值完全相反!

&&

&&这个符号在C语言中,就是and的意思,用来连接2个或多个条件判断,从左到右判断,直到遇到第一个不为True的条件停止,因为这时整个条件判断的结果已经确定,后面如果再有其它条件,也不需要判断了。

把这个思路用在Bash的命令行,也是一样的,Bash本就是可编程的Shell。如果前面的命令执行成功,则继续执行后面的命令,否则后面的命令就不用执行了。

command1 && commmand2 && ...

常见的用法有:

$ make && make install

如果make成功,则继续make install。

||

|| 就是 or 的意思,跟 && 一样,在命令行中,成了命令组合的条件判断语句。如果前面的命令执行成功,后面就不用执行了,整个条件判断已经确定为True。只有在前面的命令执行失败的情况下,才会执行后面的命令。

command1 or command2 or ...

例如:

$ echo 123 || echo 456
123

echo 123 执行成功,就不会再执行 echo 456了。

$ mkdir repos || mkdir foo
mkdir: cannot create directory ‘repos’: File exists
$ ls
foo  repos

因为repos目录已经存在,因此 mkdir repos 会失败,此时执行 mkdir foo,用 ls 命令,可以看到foo目录创建成功。

&&||混用

$ cmd1 && cmd2 || cmd3

这里只跟true or false有关,不管true是0还是1!

$ true && echo '1' || echo '2'
1
$ true && false || echo '2'
2
$ false && echo '1' || echo '2'
2
$ cmd1 || cmd2 && cmd3
$ false || echo '1' && echo '2'
1
2
$ false || false && echo '2'
$ true || echo '1' && echo '2'
2

更多测试代码,有些还带括号:

$ true && echo '1' || echo '2'
1
$ false && echo '1' || echo '2'
2
$ false && (echo '1' || echo '2')  # no output
$ false && echo '1' || echo '2'
2
$ (true && false) && echo '1'  # no output
$ (true && false) || echo '1'
1
$ true || (echo '1' && echo '2')  # no output
$ true || echo '1' && echo '2'
2
$ (true || echo '1') && echo '2'
2

在看一个:

$ a=1
$ b=2
$ [ a == b ] || echo '1' && echo '2'
1
2
$ ([ a == b ] || echo '1') && echo '2'
1
2

网上有人称;&&||命令组合符号

重定向 >|<

这是linux命令行中的重定向符号,作用是将左边命令的输出,重定向到某个位置,可以写入文件,或者将stdout重定向到stderr。

每个 Unix/Linux 程序(命令)运行时都会默认打开三个文件描述符(file descriptor,FD):

标准输入文件(stdin):stdin的文件描述符为0,程序默认从stdin读取数据。

标准输出文件(stdout):stdout 的文件描述符为1,程序默认向stdout输出数据。

标准错误文件(stderr):stderr的文件描述符为2,程序会向stderr流中写入错误信息。(stderr没有缓存,写入stderr的数据会立即输出!)

std_stream

$ echo 'cs.pynote.net' > a.txt
$ cat a.txt
cs.pynote.net

使用 > 重定向到文件,如果文件不存在则创建,如果文件存在,先清空再写入。这个符号很容易一不小心就将文件内容清空,小心!

$ command > file
# 将 stdout 重定向到 file,注意不包括重定向stderr。
$ command < file
# 将file的内容作为命令的标准输入。
$ command 2>file
# 将stderr的内容重定向到file,注意不包括重定向stdout。
$ command > file 2>&1
# 将stdout重定向到file,同时将stderr重定向到stdout,
# 这样设置的效果就是,stdout和stderr都重定向到了file。
$ command 2>/dev/null
# 将stderr错误信息输出到/dev/null设备。
# 在Linux系统中,设备的读写跟文件读写一样,
# 写入/dev/null设备,就是写入黑洞,效果等于抑制错误信息输出。
$ command < pfile > ofile
# 将pfile作为命令的输入,将命令的stdout重定向到ofile,
# 注意没有重定向stderr。

更多关于重定向的技巧,参考exec命令设置重定向

小技巧,命令行清空文件的方法:

$ > <filename>
$ :> <filename>
$ cat /dev/null > <filename>
$ echo -n > <filename>

Windows的cmd也有重定向功能

D:\temp>ipconfig | findstr 192
D:\temp>ipconfig > a.txt
D:\temp>type a.txt

Windows的findstr类似grep命令,type类似cat命令。

追加 >>

将左面命令的输出追加到文件,如果文件不存在,则创建。

$ echo '123' >> b.txt
$ cat b.txt
123
$ echo 'abc' >> b.txt
$ cat b.txt
123
abc

注意 << 是bash的一个特殊用法,叫做 here document.

Here Document <<

$ cat << __eof
> this is here ducoment,
> hello.
> __eof
this is here ducoment,
hello.

__eof在上例中表示结束字符串,可以任意设定,只要最后一行顶格输入这个字符串,here document就结束!Here Document内部支持变量替换,支持反斜杠转义,但是不支持通配符扩展,双引号和单引号也失去语法作用,变成了普通字符。

$ command << token
  string
token
# 等同于
$ echo string | command

用here document编辑一个新文件:$ cat << __eof > kk.txt

用here document追加文件内容:$ cat << __eof >> kk.txt

Here String <<<

将符号<<<后面的内容,通过stdin传递给前面的命令。有些命令只从stdin接收输入,不接受命令行上其它参数作为输入。

$ cat <<< 'hi there'
# 等同于
$ echo 'hi there' | cat
$ md5sum <<< 'ddd'
# 等同于
$ echo 'ddd' | md5sum

md5sum命令没有string参数,传入string,只能通过重定向。

冒号[:]

bash中的冒号,就像python中的pass语句,一个语法占位符,什么都不干。冒号就是一个什么都不干的命令,它有如下作用:

  1. 定义bash函数的时候,可以用冒号作为占位命令,后续再用其它命令序列替换;
  2. 配合here ducoment,在脚本文件中,实现bash的多行注释;
function a() {
    :
}
: << __eof
comment
comment
comment
...
__eof

冒号[:]命令永远返回成功!

后台运行&

不想开太多terminal终端,或有一些进程本就适合后台运行.....有很多场景适合让一个进程后台运行,实现后台运行最简单的方式,就是在命令后面增加一个这个符号: &

$ command &

Windows的cmd窗口也可以后台启动进程,方法是start /b command

~~+

~会扩展出用户的home路径,~+类似于pwd命令:

$ echo ~
/home/xinlin
$ echo ~+
/mnt/c/Users/xinlin
$ echo ~root
/root
$ echo ~hoho
~hoho

如果遇到一个不存在的用户名,~不起作用,原样输出。

|&

If |& is used, command1’s standard error, in addition to its standard output, is connected to command2’s standard input through the pipe; it is shorthand for 2>&1 |. This implicit redirection of the standard error to the standard output is performed after any redirections specified by the command.

|& 就是 2>&1 |

这就是把前一个命令的所有输出导入管道,给下一个命令。

$变量

参考:bash特殊变量

括号

参考:bash各种括号

本文链接:https://cs.pynote.net/sf/linux/shell/202110161/

-- EOF --

-- MORE --