所谓 Shell 内建命令,就是由 Bash 自身提供的命令,而不是文件系统中的某个可执行文件。
可以使用 type 来确定一个命令是否是内建命令:
[root@localhost ~]# type cd
cd is a Shell builtin
[root@localhost ~]# type ifconfig
ifconfig is /sbin/ifconfig
由此可见,cd 是一个 Shell 内建命令,而 ifconfig 是一个外部文件,它的位置是/sbin/ifconfig
。
还记得系统变量 $PATH 吗?$PATH 变量包含的目录中几乎聚集了系统中绝大多数的可执行命令,它们都是外部命令。
通常来说,内建命令会比外部命令执行得更快,执行外部命令时不但会触发磁盘 I/O,还需要 fork 出一个单独的进程来执行,执行完成后再退出。而执行内建命令相当于调用当前 Shell 进程的一个函数。
接下来的几节我们将重点讲解几个常用的 Shell 内置命令。
一、Shell alias命令
使用 alias 命令自定义别名的语法格式为:
alias new_name='command'
比如,一般的关机命令是shutdown-h now
,写起来比较长,这时可以重新定义一个关机命令,以后就方便多了。
alias myShutdown='shutdown -h now'
注意,别名只是临时的,在代码中使用 alias 命令定义的别名只能在当前 Shell 进程中使用,在子进程和其它进程中都不能使用。当前 Shell 进程结束后,别名也随之消失。要想让别名对所有的 Shell 进程都有效,就得把别名写入 Shell 配置文件。
二、Shell echo命令
Shell 的 echo 指令是用于字符串的输出。命令格式:
echo string
您可以使用echo实现更复杂的输出格式控制。注意,echo输出字符串会自动换行。
1. 显示普通字符串
echo "It is a test"
这里的双引号完全可以省略,以下命令与上面实例效果一致:
echo It is a test
2.显示转义字符
echo "\"It is a test\""
结果将是:
"It is a test"
同样,双引号也可以省略。
3.显示变量
read 命令从标准输入中读取一行,并把输入行的每个字段的值指定给 shell 变量。
#!/bin/sh
read name
echo "$name It is a test"
以上代码保存为 test.sh,name 接收标准输入的变量,结果将是:
$ ./test.sh
OK #标准输入
OK It is a test #输出
4.显示换行
echo -e "OK! \n" # -e 开启转义
echo "It is a test"
输出结果:
OK!
It is a test
5.显示不换行
#!/bin/sh
echo -e "OK! \c" # -e 开启转义 \c 不换行
echo "It is a test"
输出结果:
OK! It is a test
6.显示结果定向至文件
echo "It is a test" > myfile #myfile若不存在,则也会创建myfile文件
7.原样输出字符串,不进行转义或取变量(用单引号)
echo '$name\"'
输出结果:
$name\"
8.显示命令执行结果
echo `date`
注意: 这里使用的是反引号 `, 而不是单引号 '。
结果将显示当前日期
Thu Jul 24 10:08:46 CST 2014
echo输出的字符串总结如下表所示:
引号类型 | 能否引用变量 | 能否引用符 | 能否引用文本格式符 |
---|---|---|---|
单引号 | 否 | 否 | 否 |
双引号 | 能 | 能 | 能 |
无引号 | 能 | 能 | 否 |
三、Shell printf 命令
本章节我们来学习 Shell 的另一个输出命令 printf。printf 命令模仿 C 语言的 printf() 程序。printf 由 POSIX 标准所定义,因此使用 printf 的脚本比使用 echo 移植性好。
printf 使用引用文本或空格分隔的参数,外面可以在 printf 中使用格式化字符串,还可以制定字符串的宽度、左右对齐方式等。默认 printf 不会像 echo 自动添加换行符,我们可以手动添加 \n。
printf 命令的语法:
printf format-string [arguments...]
参数说明:
- format-string: 为格式控制字符串
- arguments: 为参数列表。
实例1
$ echo "Hello, Shell"
Hello, Shell
$ printf "Hello, Shell\n"
Hello, Shell
接下来,我来用一个脚本来体现printf的强大功能:
#!/bin/bash
printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg
printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234
printf "%-10s %-8s %-4.2f\n" 杨过 男 48.6543
printf "%-10s %-8s %-4.2f\n" 郭芙 女 47.9876
执行脚本,输出结果如下所示:
姓名 性别 体重kg
郭靖 男 66.12
杨过 男 48.65
郭芙 女 47.99
%-10s 指一个宽度为10个字符(-表示左对齐,没有则表示右对齐),任何字符都会被显示在10个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。%-4.2f 指格式化为小数,其中.2指保留2位小数。
实例2
#!/bin/bash
# author:菜鸟教程
# url:www.runoob.com
# format-string为双引号
printf "%d %s\n" 1 "abc"
# 单引号与双引号效果一样
printf '%d %s\n' 1 "abc"
# 没有引号也可以输出
printf %s abcdef
# 格式只指定了一个参数,但多出的参数仍然会按照该格式输出,format-string 被重用
printf %s abc def
printf "%s\n" abc def
printf "%s %s %s\n" a b c d e f g h i j
# 如果没有 arguments,那么 %s 用NULL代替,%d 用 0 代替
printf "%s and %d \n"
执行脚本,输出结果如下所示:
1 abc
1 abc
abcdefabcdefabc
def
a b c
d e f
g h i
j
and 0
四、Shell read命令
Shell中的 read 命令用来从标准输入中读取数据并赋值给变量。如果没有进行重定向,默认就是从键盘读取用户输入的数据;如果进行了重定向,那么可以从文件中读取数据。
read 命令的用法为:
read [-options] [variables]
options表示选项,如下表所示;variables表示用来存储数据的变量,可以有一个,也可以有多个。options和variables都是可选的,如果没有提供变量名,那么读取的数据将存放到环境变量 REPLY 中。
选项 | 说明 |
---|---|
-a array | 把读取的数据赋值给数组 array,从下标 0 开始。 |
-d delimiter | 用字符串 delimiter 指定读取结束的位置,而不是一个换行符(读取到的数据不包括 delimiter)。 |
-e | 在获取用户输入的时候,对功能键进行编码转换,不会直接显式功能键对应的字符。 |
-n num | 读取 num 个字符,而不是整行字符。 |
-p prompt | 显示提示信息,提示内容为 prompt。 |
-r | 原样读取(Raw mode),不把反斜杠字符解释为转义字符。 |
-s | 静默模式(Silent mode),不会在屏幕上显示输入的字符。当输入密码和其它确认信息的时候,这是很有必要的。 |
-t seconds | 设置超时时间,单位为秒。如果用户没有在指定时间内输入完成,那么 read 将会返回一个非 0 的退出状态,表示读取失败。 |
-u fd | 使用文件描述符 fd 作为输入源,而不是标准输入,类似于重定向。 |
实例1
使用 read 命令给多个变量赋值:
#!/bin/bash
read -p "Enter some information > " name url age
echo "网站名字:$name"
echo "网址:$url"
echo "年龄:$age"
运行结果:
Enter some information > 博客园 http://cnblogs.com 7
网站名字:博客园
网址:http://cnblogs.com
年龄:7
本例使用了-p
选项,该选项会用一段文本来提示用户输入。注意,必须在一行内输入所有的值,不能换行,否则只能给第一个变量赋值,后续变量都会赋值失败。
实例2
在指定时间内输入密码:
#!/bin/bash
if
read -t 20 -sp "Enter password in 20 seconds(once) > " pass1 && printf "\n" && #第一次输入密码
read -t 20 -sp "Enter password in 20 seconds(again)> " pass2 && printf "\n" && #第二次输入密码
[ $pass1 == $pass2 ] #判断两次输入的密码是否相等
then
echo "Valid password"
else
echo "Invalid password"
fi
运行结果:
#如果两次输入密码相同,运行结果为:
Enter password in 20 seconds(once) >
Enter password in 20 seconds(again)>
Valid password
#如果两次输入密码不同,运行结果为:
Enter password in 20 seconds(once) >
Enter password in 20 seconds(again)>
Invalid password
#如果第一次输入超时,运行结果为:
Enter password in 20 seconds(once) > Invalid password
#如果第二次输入超时,运行结果为:
Enter password in 20 seconds(once) >
Enter password in 20 seconds(again)> Invalid password
这段代码中,我们使用&&
组合了多个命令,这些命令会依次执行,并且从整体上作为 if 语句的判断条件,只要其中一个命令执行失败(退出状态为非 0 值),整个判断条件就失败了,后续的命令也就没有必要执行了。
五、Shell test 命令
Shell中的 test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试,一般搭配 if 命令使用。
1.数值测试
实例演示:
num1=100
num2=100
if test $num1 -eq $num2
then
echo '两个数相等!'
else
echo '两个数不相等!'
fi
输出结果:
两个数相等!
2.字符串测试
实例演示:
num1="ru1noob"
num2="runoob"
if test $num1 = $num2
then
echo '两个字符串相等!'
else
echo '两个字符串不相等!'
fi
输出结果:
两个字符串不相等!
3.文件测试
实例演示:
cd /bin
if test -e ./bash
then
echo '文件已存在!'
else
echo '文件不存在!'
fi
输出结果:
文件已存在!
另外,Shell还提供了与( -a )、或( -o )、非( ! )三个逻辑操作符用于将测试条件连接起来,其优先级为:"!"最高,"-a"次之,"-o"最低。例如:
cd /bin
if test -e ./notFile -o -e ./bash
then
echo '至少有一个文件存在!'
else
echo '两个文件都不存在'
fi
输出结果:
至少有一个文件存在!
六、Shell test 命令
Shell中的 exit 命令用来退出当前 Shell 进程,并返回一个退出状态;使用 $? 可以接收这个退出状态。exit 退出状态只能是一个介于 0~255 之间的整数,其中只有 0 表示成功,其它值都表示失败。
实例演示:
#!/bin/bash
echo "befor exit"
exit 8
echo "after exit"
运行该脚本:
$ ./test.sh
befor exit
$ echo $?
8
可以看到,"after exit" 并没有输出,这说明遇到 exit 命令后,test.sh 执行就结束了。另外,我们可以紧接着使用 $? 来获取 test.sh 的退出状态。
七、Shell declare 命令
Shell中的 declare 命令用来设置变量的属性。
declare 命令的用法如下所示:
declare [+/-] [aAfFgilprtux] [变量名=变量值]
其中,- 表示设置属性,+ 表示取消属性,aAfFgilprtux 都是具体的选项,它们的含义如下表所示:
选项 | 含义 |
---|---|
-f [name] | 列出之前由用户在脚本中定义的函数名称和函数体。 |
-F [name] | 仅列出自定义函数名称。 |
-g name | 在 Shell 函数内部创建全局变量。 |
-p [name] | 显示指定变量的属性和值。 |
-a name | 声明变量为普通数组。 |
-A name | 声明变量为关联数组(支持索引下标为字符串)。 |
-i name | 将变量定义为整数型。 |
-r name[=value] | 将变量定义为只读(不可修改和删除),等价于 readonly name。 |
-x name[=value] | 将变量设置为环境变量,等价于 export name[=value]。 |
实例1
将变量声明为整数并进行计算:
#!/bin/bash
declare -i m n ret #将多个变量声明为整数
m=10
n=30
ret=$m+$n
echo $ret
运行该脚本:
$ ./test.sh
40
实例2
将变量定义为只读变量:
#!/bin/bash
declare -r n=10
n=20
运行该脚本:
$ ./test.sh
bash: n: 只读变量
参考: