bash 的 Test

原文

bash 中的 test 确实是一个让初学者迷糊的概念,但是理解了之后,发现它并没有深奥的地方。

实际场景

export NVM_DIR="/Users/jero/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"  # This loads nvm

上面是我 ~/.zshrc 文件中的一段,作用是引入 nvm 脚本。其中中括号的内容就是一个测试。 再看一段:

if [ "$(uname)" == 'Darwin' ]; then
  OS='Mac'
elif [ "$(expr substr $(uname -s) 1 5)" == 'Linux' ]; then
  OS='Linux'
else
  echo "Your platform ($(uname -a)) is not supported."
  exit 1
fi

如果使用过 Atom 编辑器,那么会知道这是 /usr/local/bin/atom 中的一段脚本,作用是判断你都机器是哪种系统。其中 if 后面中括号的内容,就是测试。

从上面大致可以看出,测试就是其他语言中很常见的真假判断。实际上, [ 是一个内置命令,你可以 man [ 查看使用说明。

test 和 [

[ 命令根据表达式 expr 求值的结果返回 0(真)或 1 (假)。注意返回的结果,写多了 js 的人通常会在这里跑坑里去。 expr 也是一个 bash 命令,你可以 man expr 来查看使用手册。简单的讲,这个命令执行表达式,并将结果写到标准输出。 [ expr ]test expr 是等价的。 我们来几个实例:

test 3 -gt 4 && echo True || echo False # False
[ 3 -gt 4 ] && echo True || echo False # False
[ 'abc' != 'def' ]; echo $? # 0

$? 是上条命令的结果,不清楚的可以参见这篇文章-gt 是比较操作符,表示大于。数值比较的相关操作,总结如下:

操作符

含义

-gt

大于

-ge

大于等于

-eq

等于

-ne

不等于

-lt

小于

-le

小于等于

来看个例子:

[ 3 -gt 4 ]; echo $?; # 1
[ 3 > 4 ]; echo $?; # 0

这个当然是假的,但是用 > 比较返回了 0 ,再看一组对比:

[ 3 > 4 ]; echo $?; # 0
[[ 3 > 4 ]]; echo $?; # 1

[[ 的结果符合我们的预期,事实证明 &&, ||, >, <[] 中有些问题,这也是为什么有 [[ 的原因。

[[

[[ 是关键字,而不是一个命令,它的操作更接近 C 系语言的风格。 [[ 的用法和 [ 差不多,来几组例子:

[[ (-d "$HOME") && ( -w "$HOME") ]]; echo $?; #0
[[ (-d "$HOME") && ( -w "$HOME") ]] && echo 'home is a writable directory' # home is a writable directory
[[ "abc def .d,x--" == a[abc]*\ ?d* ]]; echo $? #0
[[ "abc def c" == a[abc]*\ ?d* ]]; echo $? #1

上面的几个例子有字符串的匹配,有单目操作符的比较,比如 -d

常见的单目操作符

操作符

意义

-z

测试 null 字符串

-n

字符串是否非空

-d

目录

-e

存在

-f

普通文件

-r

可读

-w

可写

-N

从上次读取之后做过修改

除了 -z-n ,其他都是和文件相关的操作。

(())

这其实是一个相当强大的结构(structrue),这里主要说说和测试相关的特性。 看组例子:

(( 0 )); echo $? #0
(( 3 > 4 )); echo $? #0
(( 0 && 1 )); echo $? #0
(( 0 || 1 )); echo $? #1
(( 100 && 11 )); echo $? #1

双括号结构一般都是用在数值的计算上,起返回的结果取决于计算的结果,结果为 0,返回 1(假);结果为非 0,返回 0(真)。

参考文章

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Laoqi's Linux运维专列

sed命令扩展–转载

文本处理工具之二 sed命令详解 sed:Stream Editor文本流编辑,sed是一个“非交互式的”面向字符流的编辑器。能同时处理多个文件多行的内容,可以...

2945
来自专栏玩转JavaEE

MongoDB数据类型

上篇文章我们介绍了MongoDB的最基本的增删改查操作,也介绍了一些基础的概念,MongoDB中每条记录称作一个文档,这个文档和我们平时用的JSON有点像,但也...

3025
来自专栏转载gongluck的CSDN博客

google protobuf学习笔记:编译安装、序列化、反序列化

简介 protobuf也叫protocol buffer是google 的一种数据交换的格式,它独立于语言,独立于平台。google 提供了多种语言的实...

5515
来自专栏北京马哥教育

Linux内核中container_of函数详解

在Linux 内核中,container_of 函数使用非常广,例如 Linux内核链表 list_head、工作队列work_struct中 在Linux 内...

2449
来自专栏技术专栏

慕课网Flask高级编程实战-4.flask核心机制

在 3.8节我们通过db.create_all(app=app)的方式解决了working outside application context的错误,下面我...

853
来自专栏coder修行路

Nginx location 匹配顺序整理

Nginx location模块整理 具体的Nginx安装就不在这里描述了,这里只是为了对location的描述 Nginx环境 a. 查看当前系统cat /e...

2417
来自专栏北京马哥教育

可能是最全面的 Python 字符串拼接总结

在 Python 中字符串连接有多种方式,这里简单做个总结,应该是比较全面的了,方便以后查阅。

740
来自专栏Porschev[钟慰]的专栏

Nodejs学习笔记(十二)--- 定时任务(node-schedule)

写在之前   在实际开发项目中,会遇到很多定时任务的工作。比如:定时导出某些数据、定时发送消息或邮件给用户、定时备份什么类型的文件等等   一般可以写个定时器,...

1996
来自专栏york技术分享

sed 使用教程 - 通读篇(30分钟入门系列)

和上篇 awk 分享一样,作为通读性的分享,不想引入太过复杂的东西,依然从日常工作中碰到的 80% 的需求出发,重点阐述最重点的部门,工作原理等,普及一些对se...

39722
来自专栏Java架构师历程

JVM加载class文件的原理

当Java编译器编译好.class文件之后,我们需要使用JVM来运行这个class文件。那么最开始的工作就是要把字节码从磁盘输入到内存中,这个过程我们叫做【加载...

872

扫码关注云+社区