Shell中的特殊符号(special characters)和含义

之前写过两篇关于Bash语法的blog,分别是:

个人感觉,想要通畅地读懂bash脚本,还差一个部分,那就是符号。

个人网上的讲bash符号的文章有点乱,要么有错,要么不全,要么太深,看了也感觉用不上。很多英文的文章写的好,写的深,但是查阅起来不方便。于是,干脆我自己写一篇吧,不说我这篇写的有多好,起码名称中英文有个对应,有一些自己动手运行验证过了的小例子,很多技术细节我也注明了出处。将来如果有对细节进一步的查阅的需要,可以从这里开始。

# 井号 (crosshatch/sharp/hash)

  1. 井号开头的语句被视为代码的注释,不会被执行。

  2. 在 #!/bin/bash 中,脚本文件开头首行的#!会告诉系统这个文件是一系列命令的集合,应该被发送给#!后面指定的解释器来执行。大概都有哪些解释器呢?如下:

  3. #!/bin/sh :Executes the script using the Bourne shell or a compatible shell, with path /bin/sh

  4. #!/bin/bash :Executes the script using the Bash shell.
  5. #!/bin/csh -f :Executes the script using C shell or a compatible shell.
  6. #!/usr/bin/perl -T :Executes the script using perl with the option of taint checks
  7. #!/usr/bin/env python :Executes the script using python by looking up the path to the python interpreter automatically from the environment variables

~ 波浪号(tilde)

Bash提供了一些用~开头的变量,这些变量的展开叫做Tilde Expansions,也就是将这些缩写转换成它们代表的目录名称的过程。

  1. 与$HOME一样,代表当前用户的home directory.

  2. ~username, 代表其他某用户的home directory.

  3. ~+, 代表当前的工作目录, 与$PWD一样。

  4. ~-,代表上一个工作目录,与$OLDPWD一样。

  5. ~1, ~2, ~-1, ~-0 分别代表目录栈中的编号为1的,编号为2的,编号为倒数第2的,倒数第一的目录。相当于’dirs +1’, ‘dirs +2’, ‘dirs -1’, ‘dirs –0’.

; 分号(semicolon)

分号用来分隔两个命令,比如命令 echo a; echo b 就是告诉bash,echo a 和 echo b 是两个不同的命令,需要一个接一个地分开运行。参考这里

;; 双分号(double semicolon)

双分号;; 仅用在case结构中,标志一个选项的结束,类似于C语言中的break。

. 点号(dot)

一个 dot 代表当前目录,两个 dot 代表上层目录。如果档案名称以 dot 开头,该档案就属特殊档案,用 ls 指令必须加上 -a 选项才会显示。除此之外,在 regular expression 中,一个 dot 代表匹配一个字元。

‘string’ 单引号 (single quote)
被单引号用括住的内容,将被视为单一字串。在引号内的代表变量的$符号,没有作用,也就是说,$符号被视为一般符号处理,防止任何变量替换。

“string” 双引号 (double quote)
被双引号用括住的内容,将被视为单一字串。它防止通配符扩展,但允许变量扩展。这点与单引数的处理方式不同。

command 反引号 (backtick)

反引号不是一种引号,它有特殊的意义。任何被反引号括起来的东西都会在主命令执行之前先被shell求值(或执行),并且反引号括起来的东西的求值(或执行)的输出会被主命令使用到。

在前面的单双引号,括住的是字串,但如果该字串是一列命令列,会怎样?命令会执行么?

答案是不会执行。要处理这种情况,我们得用反引号。

在反引号内的 date +%F 会被视为指令,执行的结果会带入 $fdv 变量中。

下面的例子里,先创建一个名为lucky的user,可以看到他的uid为1001.

查看当前用户的信息,名为yunlong的用户的uid为1000. 可以看到/home/lucky 是lucky用户的home directory,owner是lucky。

然后,我们利用命令 chown id -u /home/lucky, 把/home/lucky的owner换成了yunlong。注意这里对于反引号的使用。

, 逗号 (comma)

逗号可以有下面这些用途:

  1. 括号扩展(brace expansion)

tee 命令的作用是从标准输入读取(standard input)之后,将读取来的信息同时写入标准输出(standard output)和一个或多个文件中。详情见这里

  1. 在let语句中,或者在与其作用等价的(())构造中分隔算数操作。

  2. 可以在for语句中,分隔不同的index变量,避免在for循环体中进行操作。

  3. 逗号还可以用在Bash4中,把字符串变成小写。

/ 斜杠 (forward slash)

在路径表示时,斜杠代表目录。通常单一的斜杠 / 代表 root 根目录的意思;在四则运算中,斜杠代表除法的符号。

\ 反斜杠(backslash/escape)

在交互模式下的escape符号,有几个作用:

  1. 放在指令前,有取消 aliases 的作用;

type rm

rm is aliased to `rm -i’
\rm .*.log
上例,作者在 rm 指令前加上 escape 字符,作用是暂时取消别名的功能,将 rm 指令还原。

  1. 转义字符,放在特殊符号前,则该特殊符号的作用消失;

  2. 放在指令的最末端,表示指令连接下一行。

| 竖线 bar/pipe/vertical bar

pipeline 是 UNIX 系统,基础且重要的观念。连结上个指令的标准输出,做为下个指令的标准输入。

善用这个观念,对精简 script 有相当的帮助。

! 叹号 exclamation mark/bang

通常它代表反逻辑的作用,譬如条件侦测中,用 != 来代表”不等于”

if [ “$?” != 0 ] ; then echo “Executes error”; elif then echo “Executes successfully”; fi;

这个例子里,除了展示了叹号的用法,还包含了如何把if语句写在一行里的方法,还有一个利用上面讲过的反斜杠把一个一行的if语句写成多行的方法。

在正则表达式里,可以使用 !字符在正则表达式之前对其求反。也就是说,仅当字符串与表达式的其余部分不匹配时,才认为字符串已匹配。

注意,网上的很多名为《shell脚本中一些特殊符号》的文章里,在讲叹号是给出的例子里使用叹号是不正确的。

应该使用^符号,来对字符范围取反。如下:

: 冒号 colon

在 bash 中,这是一个内建指令, 这个指令”什么事都不干(no-op)”,但返回状态值 0 (Bash里返回值为0表示正常执行结束,非0表示出了问题)。

比如,if语句利用上冒号可以写成这样:

if [ “$?” != 0 ]; then :; else echo “Execute successfully”; fi

? 问号 (question mark)

在文件名的匹配中,用作单字符的通配符。注意,问号代表的是只有一个字符的通配符,数字和字母都可以匹配。

* 星号 (asterisk/star)

星号是bash中的任意字符序列通配符,包括没有字符的情况都可以匹配。

** 双星号 (double-asterisk)

双星号(**)在多个段中尝试匹配零个或多个字符,它用于对嵌套目录中的文件进行通配。

举例:

Tests/*/.js

这里,匹配的文件被限制在Test目录中。会被匹配的文件包括 Tests/HelloWorld.js, Tests/UI/HelloWorld.js, Tests/UI/Feature1/HelloWorld.js

另一个就是幂运算。

$ 美元符号(dollar sign)
变量替换(Variable Substitution)的代表符号。 一个变量名字前面带上美元符号,表明这是个变量。可以用美元符带上这个变量的名字对其进行引用。
另外,在 Regular Expressions 里被定义为匹配行尾 (end-of-line)。

${} 变量扩展(variable substitution)

${ }用于变量替换。一般情况下,$var 与${var} 并没有啥不一样。但是用 ${ } 会比较精确的界定变量名称的范围。

$ AB=string0
$ A=string1
$ echo $AB
string0
原本是打算先将 $A 的结果替换出来,然后再补一个 B 字母于其后.

但在命令行上,真正的结果却是只会提换变量名称为 AB 的值出来…

若使用 ${ } 就没问题了:
$ echo ${A}B
string1B

$() 命令替换 (command substitution,与一对反引号相同)

在 bash shell 中,$( ) 与 (反引号) 都是用来做命令替换用(command substitution)的。

例如version=$(uname -r)和version=uname -r都可以是version得到内核的版本号。

  1. 反引号的命令替换基本上可在全部的 unix shell 中使用,若写成 shell script ,其移植性比较高。但是,反引号容易打错或看错。

  2. $()并不是所有shell都支持。

$(()) 和 $[] 算数扩展(arithmetic expansion)

它们是一样的,都是进行数学运算的。支持+ – * / %:分别为 “加、减、乘、除、取模”。但是注意,bash只能作整数运算,对于浮点数是当作字符串处理的。

二者的区别是$[]已经是淘汰的,弃用的语法了,现在已经完全被$(())替代了。

() 小括号(parentheses) 指令群组 (command group)

小括号之内的一系列命令,会在一个新创建的subshell中执行。由于小括号内的命令是在subshell中执行的,所以其内部的变量赋值在执行之后不会持续。

Placing a list of commands between parentheses causes a subshell environment to be created (see Command Execution Environment), and each of the commands in list to be executed in that subshell. Since the list is executed in a subshell, variable assignments do not remain in effect after the subshell completes.

{} 花括号(braces)指令群组 (command group)

花括号之内的一系列指令会在当前的shell的上下文中执行。不会创建subshell。 列表之后的分号(或者换行)是必须要有的。

Placing a list of commands between curly braces causes the list to be executed in the current shell context. No subshell is created. The semicolon (or newline) following list is required.

(()) 双括号 (Double-Parentheses)

跟let命令一样,双括号允许在其中进行算数扩展和求值。 最简单的一个例子, a=$((5+3)), 会将5+3的结果赋值给a。 双括号还是一个在bash中使用的C语言风格的操作变量的方法,举个例子 ((var++)).

[] 单方括号 (Single Square Brackets)

单方括号是内置命令test的另一种形式,方括号括住的命令会被验证其是否为真。 注意,空字符串为false,非空字符串为true。

既然是test命令的另一种形式,那么test命令的各种选项就也是可以应用的。

[[]] 双方括号 (Double Square Brackets)

[[ 是新的,提高版的[, 双方括号是个关键字,不是一个程序。双方框更好用,比较见下表。

英文原文如下:

[ : test implements the old, portable syntax of the command. In almost all shells (the oldest Bourne shells are the exception), [ is a synonym for test (but requires a final argument of ]).

[[ : is a new, improved version of it, and it is a keyword rather than a program. This makes it easier to use

&& 逻辑与, || 逻辑或 (Logical Operators)

双&&符号在Bash中意思是逻辑与(AND),并且可以用来分隔几个顺序执行的命令。

举例:

cd /root/ && echo "I've got root"

& 后台工作 (Single Ampersand)

在Bash中, &是控制字符,放在命令的末尾,其作用是让命令在后台运行,也就是说在另外的一个subshell里,以异步的方式,如同一个job一样的执行。当前的Shell会立即回到等待用户输入的状态,并且返回值为0.

举例:

shell会给出后台运行命令的process ID (PID), 这个ID会存储在$! 变量中。

$ ./myscript.py &
[1] 1337

后面可以通过$!变量对该进程进行引用。
$ echo $!

1337

一旦生成了新的后台进程,这个进程会出现在job列表中。
$ jobs
[1]+ Running ./myscript.py &

foregroud命令可以把这个进程拿回前台。
fg

  • 加号, -减号, * 乘号, / 除号

比较简单,不说了。

= 等号(赋值), == 双等号 (判断相等), != 不等于号

简单,也不说了。

^ 折音号 (circumflex/caret)

这个符号在正则表达式中,代表行的开头位置,在[]中也与!(叹号)一样表示非,即求反。

>, >>,

这里符号比较多,一个一个简介吧。

  1. command > file — 将输出重定向到file

  2. command < file — 将输入重定向到file,确切的说是把file中的内容拿来作为command的输入。

  3. command >> file — 将输出以追加的方式重定向到file

  4. n >& m — 将输出文件m和n合并

  5. n

Original: https://www.cnblogs.com/awpatp/p/14146625.html
Author: 中道学友
Title: Shell中的特殊符号(special characters)和含义

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

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

(0)

大家都在看

  • ROS::message_filters中的一个报错(mt::TimeStamp……)

    <p>&#x300E;&#x65B9;&#x4FBF;&#x68C0;&#x7D22;&#x300F; ros::Tim…

    Linux 2023年6月14日
    071
  • redis报错OOM command not allowed when used memory > ‘maxmemory’

    登录到redis上查询 ./redis-cli -h IP -p port -a passwdredis>info memory 查询,内存已耗尽 查询配置文件,发现之前配置…

    Linux 2023年5月28日
    083
  • 维修数列代码及简易题解

    总体方案:将左右端点分别转到根和根的右儿子,将目标序列挤到以根的右儿子的左儿子为根的子树中,然后进行一系列骚操作即可 建树:用类似线段树的方法建树,递归即可,注意加两个边界点 插入…

    Linux 2023年6月6日
    0109
  • Redis具体解释

    2、 redis.windows.conf各项配置參数介绍 默认情况下,redis不是在后台模式执行的,假设须要在后台进程执行。把该项的值更改为yes。默觉得no daemoniz…

    Linux 2023年5月28日
    085
  • uniapp封装request请求,常用公共函数等,非常实用

    1、项目目录如下图,utils目录下的文件和main.js文件在下面可以直接下载使用 2、demo案例,前端代码 php;gutter:true; export default {…

    Linux 2023年6月7日
    091
  • 1s 创建100G文件,最快的方法是?

    在我们日常工作中,为了验证开发的功能,比如:文件上传功能或者算法的处理效率等,经常需要一些大文件进行测试,有时在四处找了一顿之后,发现竟然没有一个合适的,虽然 Linux 中也有一…

    Linux 2023年5月27日
    075
  • Nginx/Tengine安装配置详解

    1 概念 Nginx (“engine x”) 是一个高性能的 HTTP 和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器。官方测试…

    Linux 2023年5月27日
    0120
  • 5.1 Vim及其安装

    通过前面的学习我们知道,Linux 系统中”一切皆文件”,因此当我们在命令行下更改文件内容时,不可避免地要用到文本编辑器。 作为一名 Linux 初学者,你…

    Linux 2023年6月7日
    091
  • Elasticsearch7.X 安装(CentOS7)

    需要Java环境最低1.8起步 Elasticsearch时隔三年出来了8.0版本,最低需要JDK17 一、 获取Elasticsearch7.x安装包 获取链接 Elastics…

    Linux 2023年6月13日
    0104
  • bash是什么?

    ​ –解释器,启动器 ​ –解释器: ​ 用户交互输入 如vim 文本文件输入 !/bin/bash *!/usr/bin/python bash/sh f…

    Linux 2023年5月27日
    073
  • GFS-Google 文件系统

    GFS分布式文件系统 简介 GFS是一个可扩展的分布式文件系统,用于大型的、分布式的、对大量数据进行访问的应用。它运行于廉价的普通硬件上,并提供容错功能。它可以给大量的用户提供总体…

    Linux 2023年6月13日
    076
  • shell之文件路径截取

    最近写脚本,需要对脚本中函数传递的路径参数进行截取,发现了以下比较好用的方法,记录下: file=/dir1/dir2/dir3/my.file.txt 我们可以用${ }分别替换…

    Linux 2023年5月28日
    076
  • C++11

    1.新增不需要赋值即可初始化 //C++98 int a = 1; int* p1 = new int[3]; Date d1(2022, 9, 26); //C++11 Date…

    Linux 2023年6月13日
    099
  • 微信小程序全局变量的设置、使用、修改过程解析

    微信小程序全局变量的设置、使用、修改过程解析 全局变量的设置 在miniprogram > app.js 文件中设置,globalData对象就是存储全局变量的。 php;g…

    Linux 2023年6月7日
    088
  • Python 装饰器

    直接进入主题 原代码 以下是原代码,要求给改代码添加统计时间功能 版本1(直接在原函数上修改) 可能有的同学就做出了下面这个版本 版本2(将函数当做参数传入) 经过修改上面的版本我…

    Linux 2023年6月13日
    088
  • [ Linux ] 设置服务器开机自启端口

    https://www.cnblogs.com/yeungchie/ 需要用到的工具: crontab iptables crontab.set SHELL=/bin/bash P…

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