Linux Shell之表达式

严格来说,shell中没有表达式的概念。Shell本身其实只是一堆命令的集合,当然也不是胡乱的堆在一起,而是有一定的组织。只是这个组织不那么严谨,所以本文不是要真的总结所谓的表达式,而是把shell中一些犄角旮旯的东西拼凑在一起,实在不知道它们属于那个分类。。


  • 命令代换

    其实就是这篇文章中的反引号所起的作用。但是命令代换还有另一种形式,如下:

m@meng:~/scripts$ m=`date`
m@meng:~/scripts$ echo $m
2015年 06月 25日 星期四 10:40:24 CST
m@meng:~/scripts$ n=$(date)
m@meng:~/scripts$ echo $n
2015年 06月 25日 星期四 10:40:37 CST

也就是说,`command`和$(command)的效果是一样的。


  • 算术代换

    前面说过,将一个变量声明为整数类型时,它就可以做算术运算,或者说,赋值给这个变量的数字不再被当成字符串,而是真正的数字。如果没有这个整数声明,那么把一个数字或算术表达式赋值给一个变量时,它的值仍被视为普通字符串。

    但是现在,有另一个方法可以达到这个效果,就是符号$((expr))。处于内括号中的变量将直接被视为整数,而不必事先声明其为整数类型。如下:

m@meng:~/scripts$ r=3+4
m@meng:~/scripts$ echo $r
3+4
m@meng:~/scripts$ echo $(($r))
7
m@meng:~/scripts$ echo $(($r+3))
10

不过,$(()) 中只能用+-*/和()运算符,并且只能做整数运算。


  • 引号

    Shell脚本中的单引号和双引号一样都是字符串的界定符,两者的区别在于,单引号中的所有字符都被视为普通字符,而舍弃其功能含义。比如’$’是变量值提取符,但是放在单引号中就是’\$’的字面值,如下:

m@meng:~/scripts$ q=5
m@meng:~/scripts$ echo "$q"
5
m@meng:~/scripts$ echo ‘$q‘
$q

所以,在单引号中使用变量一定要小心。

所谓界定符,其实就是将界定符内的字符串视为一个整体,而不会被空格等分隔符打断。

在双引号内,所有的特殊字符将保持其转义含义,如上面的’$’。如果想让双引号中的某个特殊字符恢复其本来面目,即取其字面值,可以在它前面添加转义字符’\’,如下:

m@meng:~/scripts$ echo "\$q"
$q

  • 退出状态

    在shell中,可以认为一条命令就是一个表达式。表达式都是有值的,而一条命令的值是什么呢?是它的执行结果吗?比如ls列出来的文件?实际上,可以把命令的出口状态视为“命令表达式”的值:命令执行完毕后,会有一个出口状态来表示这条命令是否执行成功,一般情况下,shell中命令执行成功出口状态为0;失败为1或其他非0值。可以使用系统变量“#?”来查询上一条命令的出口状态,如:

m@meng:~/scripts$ grep m new
m@meng:~/scripts$ echo $?
1
m@meng:~/scripts$ cat new
的
m@meng:~/scripts$ echo $?
0
m@meng:~/scripts$ m=4
m@meng:~/scripts$ echo $?
0

上例,grep命令在new文件中没有找到字符”m”,所以其出口状态为1;其他都为0,包括赋值语句。

退出状态经常用做if语句的判断条件。


  • test表达式

    虽然可以直接使用命令的出口状态作为if、while等语句的判断条件,但是更常使用的却是test等专门的测试命令。

    test命令的语法为:

    test 表达式

    test主要用来执行三类测试:文件属性、数值比较、字符串比较。如果测试结果为真,则该命令的Exit Status为0,如果测试结果为假,则命令的Exit Status为1。

    • 文件测试

      格式为: test options file。主要的options包括:

      • -e 测试file的存在性,若存在则值为0;否则为1。这个结果跟执行普通命令得到的出口状态是一致的。
      • -d 测试file是否为目录,是为0;否为1。
      • -f 若file是普通文件,结果为真(即,值为0).
      • -s 测试文件是否为非空,若file存在且非空,为0;否则,即不存在或者是空文件,为1。
      • -r file存在且只读,为真。
      • -w file存在且可写,为真。
      • -x file存在且可执行,为真。
    • 数字测试

      数字测试的比较运算符竟然使用的是文字,对比如下(左侧是C语言使用的传统的运算符,右侧是shell使用的):

      == : -eq

      != : -ne

      > : -gt

      \< : -lt

      >= : -ge

      \<= : -le

    • 字符串测试

      -z str: 若str的长度是0,结果为真(谨记:真 <==> $? == 0)

      -n str: 若str的长度不是0,结果为真

      s1 = s2 : 两个字符串相等,结果为真

      s1 != s2 : 两个字符串不等,结果为真

      str : 不加任何选项来测试str,效果同-n


  • [ ] 表达式

    实际上,只有 [ 是命令,而 ] 只是界定符。[ 命令与test命令基本相同,唯一的区别就是格式不同,[ 命令需要将要测试的表达式置于括号中,###且表达式左右两边分别要和[ ]留一个空格###,如[ -z “empty” ]。据说,[ 命令的效率稍微高一些,我没验证过。

    还有一点:###[ 命令不支持运算符“>”和“<”###,所以对于字符串比较运算的支持可能差一点,这是唯二的区别。。。。


  • [[ ]]表达式

    扩展了[ ]命令,首先就是支持了运算符“>”和“<”,另外还支持逻辑运算&&,||,!,如下:

m@meng:~/scripts$ [ er > et ]
m@meng:~/scripts$ echo $?
0
m@meng:~/scripts$ [[ er > et ]]
m@meng:~/scripts$ echo $?
1

显然,er > et结果应该为假,所以测试表达式的出口状态是1。但是[]没有效果,而[[ ]]测试正确。

m@meng:~/scripts$ [ er > et || er < et ]
bash: [: 缺少 `]`
er:未找到命令
m@meng:~/scripts$ [[ er > et || er < et ]]
m@meng:~/scripts$ echo $?
0
m@meng:~/scripts$ [[ er > et && er < et ]]
m@meng:~/scripts$ echo $?
1

  • 算术表达式

    • (( ))表达式

      似乎有点凌乱了,(( ))与$(( ))的区别在于,后者可以把计算结果提取出来作为一个值使用,我个人感觉,’$’这个符号就是用来提取值的,比如引用变量的时候也用它。而符号(( ))只是完成计算本身,至于保存结果,虽然也可以,但是不是主业。还是直接看命令吧:

m@meng:~/scripts$ ((m=4-2))
m@meng:~/scripts$ echo $m
2
m@meng:~/scripts$ m=$((4-2))
m@meng:~/scripts$ echo $m
2

这意味着,((m=4-2))和m=$((4-2))效果是一样的,也就是说在(())内部可以直接完成赋值。

~~~~

m@meng:~/scripts$ echo $((4-2))
2
m@meng:~/scripts$ echo ((4-2))
bash: 未预期的符号 ‘(‘ 附近有语法错误

这说明,(())不负责保存结果,想要结果的话,用’$’来提取。

~~~~

m@meng:~/scripts$ m=3;n=2
m@meng:~/scripts$ echo $((m-n))
1

这说明,在(())内部使用变量时,不需要添加’$’符号。

~~~~

m@meng:~/scripts$ m=3;n=2
m@meng:~/scripts$ echo $((m<n))
0
m@meng:~/scripts$ echo $((m>n))
1

显然,(())还支持比较运算,唯一的问题是,它的出口状态与test等其他命令恰好相反!

~~~~

总结一下这个表达式:

1、只支持整数运算;

2、支持的运算包括:=(赋值)、==(相等)、>= <= < > % + - * / -= += /= *= %=,很丰富了。

  • let表达式

    与上面那个基本一样,只是格式不同罢了,let中表达式写在let后面,而不是括号中。另外,由于不像(())有天然的界定符,所以算式中有空格时,需要用引号括起来。

  • expr表达式

    以后再写吧,好累。。。上面的已经够用了。


逻辑运算

主要有&&、||、-a、-o、!和(),用来计算表达式之间的逻辑运算,支持用括号()来进行组合,逻辑运算符和表达式之间要有空格

[[]]命令只支持符号,不支持-a和-o选项。

[email protected]:~/scripts$ [[ er > et -o er < et ]]
bash: 条件表达式中有语法错误
bash: ‘-o‘ 附近有语法错误

完。

时间: 2024-11-05 12:20:48

Linux Shell之表达式的相关文章

Linux - Shell - 算术表达式 - 算数运算

概述 shell 中基于 $(()) 的 算数运算 背景 复习 shell 脚本 凑数吧 准备 环境 os centos7 1. 算数运算 代码 #!/bin/bash # $(()) 的数学运算, 里面的内容, 被解释为 算数表达式 # $(()) 内的变量, 可以不加 $ # 只看 正整数 arg1=4 arg2=5 # 算数运算 # 1. + var1=$((arg1+arg2)) echo $var1 # 2. - var2=$((arg1-arg2)) echo $var2 # 3.

Linux - Shell - 算数表达式 - 位运算

概述 shell 中基于 $(()) 的 位运算 背景 复习 shell 脚本 凑数吧 准备 环境 os centos7 1. 位运算 代码 #!/bin/bash # 位运算 arg1=2 arg2=8 # 位运算 # 1. << var1=$((arg1 << 2)) echo $var1 # 2. >> var2=$((arg1 >> 1)) echo $var2 # 3. & var3=$((arg1&arg2)) echo $var

Linux Shell——正在表达式

正则 grep 匹配,并能显示颜色 过滤,显示行号,区分大小写 grep -v取反 取上2行,下2行,上下两行 以# 开头的行 把不是以#开头打印出来,例如,在看配置文件时可以用到 匹配所有 一次o或多次,*是0次o或者多次 ?重复次数0或1 | 或者 不区分大小写 .  任意一个字符 *  0个或多个*前面的字符 .*  通配 {}  表示范围前面字符 +  一个或多个,前面字符 ? 0个或1个前面字符 |  或者 sed 匹配和替换 -n 不打印无关的行 r不脱译 匹配2~5行 打印25~末

Linux shell脚本基础学习详细介绍(完整版)一

Linux shell脚本基础学习这里我们先来第一讲,介绍shell的语法基础,开头.注释.变量和 环境变量,向大家做一个基础的介绍,虽然不涉及具体东西,但是打好基础是以后学习轻松地前提.1. Linux 脚本编写基础◆1.1 语法基本介绍 1.1.1 开头 程序必须以下面的行开始(必须方在文件的第一行): #!/bin/sh 符号#!用来告诉系统它后面的参数是用来执行该文件的程序.在这个例子中我们使用/bin/sh来执行程序. 当编辑好脚本时,如果要执行该脚本,还必须使其可执行. 要使脚本可执

Linux shell脚本基础学习详细介绍(完整版)二

详细介绍Linux shell脚本基础学习(五) Linux shell脚本基础前面我们在介绍Linux shell脚本的控制流程时,还有一部分内容没讲就是有关here document的内容这里继续. Linux shell脚本基础已经被分成好几个部分了,这里对控制流程的内容也就马上讲完了,这是最后一部分关于here document,这里举例稍微有点复杂,我们慢慢来分析这个复杂Linux shell脚本. 6. Here documents 当要将几行文字传递给一个命令时,here docu

linux shell中的比较符号与特殊符号介绍

shell字符串比较.判断是否为数字  二元比较操作符,比较变量或者比较数字.注意数字与字符串的区别.  整数比较  -eq 等于,如:if [ "$a" -eq "$b" ]  -ne  不等于,如:if [ "$a" -ne "$b" ]  -gt 大于,如:if [ "$a" -gt "$b" ]  -ge 大于等于,如:if [  "$a" -ge "

【转】十分有用的linux shell学习总结

在最近的日常工作中由于经常会和Linux服务器打交道,如Oracle性能优化.我们 数据采集服务器的资源利用率监控,以及Debug服务器代码并解决其效率和稳定性等问题.因此这段时间总结的有关Linux Shell的系列博客就给予了我极大的帮助,然而在实际的使用中却发现,有的时候确实忘记了某个技术点或某个Shell命令的使用方式曾经在哪一篇博客中 予以了说明,所以不得不多次点击多篇博客,直到找到想要那篇的为止,鉴于此,为了方便我们每个人的查阅,这里特别给出了前十二篇系列博客的目录以供大家参 阅和查

Linux shell脚本流程控制

博主搬家至51CTO,初来乍到,请多指教. 此次我们来通过实例解析Linux shell脚本流程控制 Linux shell脚本流程控制可分为三类:顺序执行,条件选择执行,循环执行 顺序执行:简单理解就是逐行执行脚本内容,逐行解读,逐行执行.(此处不做实例解析) 条件选择执行:可以理解为先进行某一条件的判断选择,再决定执行怎样的脚本内容.常见语句if case 条件选择语句:if if语句用法: 单分支 if 判断条件;then 条件为真的分支代码 fi 双分支 if 判断条件; then 条件

Linux shell 变量 数学 运算

Abstract : 1)  Linux shell 中使用 let , [ ] ,(( )) 三种运算符操作 shell 变量进行简单的基本运算: 2)Linux shell 中使用 expr 与 bc 两个程序实现高级运算: 1, Linux shell 变量的基本运算 数值作为常规变量直接赋值给变量,并且以字符串形式保存. 1.1 let 命令可以用于直接执行基本操作:         当我使用 let 的时候,我们不使用 $ 符号引用变量. no1=7; no2=8; echo "---