Shell编程速查手册

https://blog.atime.me/note/shell-scripting-summary.html

总结一下日常Shell脚本里常用的知识,忘记时方便查阅。

常见的shell

常见的Linux发行版里,默认的shell一般是dash(sh)或bash,不同的shell对脚本的支持也各不相同。若无特殊说明,以下shell知识都是基于Ubuntu 14.04 x86_64系统上的bash 4.3

Shell编程书籍

只看过Advanced Bash-Scripting Guide,简称ABS。感觉这本电子书内容详尽,例子很多,作者维护地也很积极。

以下只总结一些关键知识点。

变量

变量赋值

赋值操作符左右不能有空白字符。

a=1024

# 清空变量
a=
unset a

# 变量清空后,在做计算时为0
let "b = 100 / (a + 2)"
echo $b
# 50

${} $() $(())

${ls}$ls一样,都是取变量ls的值,$(ls)则表示执行命令ls。

$(( e ))则返回表达式e的值,见下文的算术操作

假设当前目录下有两个文件fileA和fileB,下同。

ls=1024

echo $ls
# 1024
echo ${ls}
# 1024
echo $(ls)
# fileA fileB
echo `ls`
# fileA fileB

echo $(( 1 + 2 ))
# 3

间接引用

以上变量赋值称为直接引用,例如

a="b"
echo ${a}
# b

间接引用其实就是获取变量的值的值,在上面的例子里就是变量b的值,可以使用${!a}来获取。

a="b"
b=2
echo ${!a}
# 2

弱引用 vs 强引用

双引号和单引号的区别。

a=1024

echo "$a"
# 1024
$ echo ‘$a‘
# $a

双引号还能在echo的时候保留变量里的换行符。

a=`ls -1`

echo $a
# 输出里的换行符变成了空格
# fileA fileB

echo "$a"
# fileA
# fileB

特殊变量

特殊变量

true和false

truefalse命令的作用就类似c语言里的true和false关键字。

数组

bash支持一维数组

a=(1 2 3 4 55)

echo ${a[0]}
# 1
echo ${a[4]}
# 5
echo ${a[100]}
#

# 获取全部数组元素
echo ${a[*]}
# 1 2 3 4 5
echo ${a[@]}
# 1 2 3 4 5

# 获取长度
echo ${#a[4]}
# 2
echo ${#a[*]}
# 5
echo ${#a[@]}
# 5

需要注意的几点

  • 数组越界不返回(null)
  • ${arr[*]}${arr[@]}返回全部元素
  • ${#arr[N]}返回对应元素(或全部元素)的字符串长度

算术操作

简单的整数计算可以通过bash内置的let(())来实现,详细文档可参考Shell Arithmetic

(( a = (1 + 101) / 3 ))
let "a = (1 + 101) / 3"

复杂的数学计算或浮点数计算可以使用bc工具,见下文。

字符串操作

需要注意的是,shell是弱类型的。

注: str=string, pat=pattern, rep=replacement

  • 字符串替换: ${str/pat/rep}${s//pat/rep}${s/#pat/rep}${s/%pat/rep}

    a="hello world"
    b=${a/world/Tom}
    
    echo $b
    # hello Tom
    
    # 全部替换
    a="aaaa"
    echo ${a//a/b}
    # bbbb
    
    # 只替换头部
    a="123456"
    echo ${a/#123/ABC}
    # ABC456
    echo ${a/#456/ABC}
    # 123456
    
    # 只替换尾部
    a="123456"
    echo ${a/%123/ABC}
    # 123456
    echo ${a/%456/ABC}
    # 123ABC
    
  • 获取字符串长度: ${#str}
    a="hello world"
    echo ${#a}
    # 11
    
  • 提取字串: ${str:position:length}
    a="123456"
    echo ${a:1:3}
    # 234
    
  • 删除字串
    • ${s#pat}: 从开头删除最短的匹配
    • ${s##pat}: 从开头删除最长的匹配
    • ${s%pat}: 从结尾删除最短的匹配
    • ${s%%pat}: 从结尾删除最长的匹配

    例子

    a="Good morning, Tom"
    
    echo ${a#G* }
    # morning, Tom
    
    echo ${a##G* }
    # Tom
    
    echo ${a%o*m}
    # Good morning, T
    
    echo ${a%%o*m}
    # G
    

    这里的pattern仅支持有限的正则表达式操作,见模式匹配

条件表达式

常用于if和while语句中,退出状态为0则表示true,不为0表示false。也可单独使用

[ vs [[

bash支持[内置命令(非/usr/bin/[1)和[[关键字来构造条件表达式,[test内置命令的效果是一样的;[[构造的表达式类似c语言,相对更直观一些,支持的操作符也更多一些。

[支持的比较操作符

  • 数字比较

    • -eq: 相等(equal),[ $a -eq $b ]
    • -ne: 不相等(not equal)
    • -gt: 大于(greater than)
    • -lt: 小于(less than)
    • -ge: 大于等于(greater than or equal to)
    • -le: 小于等于(less than or equal to)
  • 字符串比较,进行字符串比较的时候尽量带上引号
    • =: 相等, [[ "$a" = "$b" ]],注意等号两边必须保留空格。
    • ==: 相等, 在[[[中表现不同2
    • !=: 不相等
    • <: 小于,按字典序比较
    • >: 大于,按字典序比较
    • -z: 字符串是null(""),即长度为0
    • -n: 字符串不是null,此时必须将变量"引"起来:[ -n "$str" ]
  • 常用的文件比较,所有的文件操作符见ABS 7.2. File test operators
    • -e: 文件存在
    • -f: 是regular文件,可使用ls -l查看
    • -s: 文件大小不是0
    • -d: 文件是目录
    • -h: 文件是软链接
    • -L: 同上,文件是软链接
    • -r: 当前用户对文件有读权限
    • -w: 当前用户对文件有写权限
    • -x: 当前用户对文件有执行权限
    • a -nt b: 文件a比文件b新(修改时间更晚)
    • a -ot b: 文件a比文件b旧(修改时间更早)
  • 其他
    • !: 逻辑非
    • -a: 逻辑与,类似于c语言的&,每个后续的表达式都要比较
    • -o: 逻辑或,类似于c语言的|,每个后续的表达式都要比较

[[支持的比较操作符

  • 所有[中支持的操作符
  • 扩展的数字比较
    • <: 小于
    • >: 大于
    • <=: 小于等于
    • >=: 大于等于
  • 其他扩展
    • &&: 逻辑与,类似于c语言的&&,遇到true便退出,不再比较后续的表达式
    • ||: 逻辑或,类似于c语言的||,遇到false便退出,不再比较后续的表达式

操作符优先级

不要依赖优先级,依赖括号()

下面由高到低列出常见的操作符的优先级,全面的优先级表见ABS 8.4. Operator Precedence

  1. ++ -- 自增和自减
  2. ! 逻辑非
  3. ** 乘方
  4. * / % 乘除和取模
  5. + - 加减
  6. -z -n 一元字符串比较操作符
  7. -e -f -x 等一元文件比较操作符
  8. < -lt <= > 等二元数字/字符串比较操作符
  9. -nt -ot 等二元文件比较操作符
  10. -a && 逻辑与
  11. -o || 逻辑或
  12. = 赋值操作符

变量的真假

  • 未初始化,被赋值为null或被unset的变量在条件表达式里都是假。

    a=
    a2=""  # 也是null
    b=1; unset b
    
    if [ ! $a ]; then echo "a is false"; fi
    # a is false
    if [ ! $a2 ]; then echo "a2 is false"; fi
    # a2 is false
    if [ ! $b ]; then echo "b is false"; fi
    # b is false
    if [ ! $c ]; then echo "c is false"; fi
    # c is false
    
  • 其他正常初始化的变量都是真
    a=1
    b=0
    c=-1
    d="false"
    
    if [ $a ]; then echo "a is true"; fi
    # a is true
    if [ $b ]; then echo "b is true"; fi
    # b is true
    if [ $c ]; then echo "c is true"; fi
    # c is true
    if [ $d ]; then echo "d is true"; fi
    # d is true
    

命令列表里的与和或

除了在条件表达式中,bash还支持在条件命令列表里使用&&||,作用类似c语言里的&&||

  • &&: 仅当前一条命令的退出状态为0(true)时才执行下一条命令。
  • ||: 仅当前一条命令的退出状态不为0(false)时才执行下一条命令。

例如

true && echo hello
# hello

[ 1 -eq 1 ] && echo hello
# hello

false || echo hello
# hello

控制语句

if语句

if [condition]; then
    commands...
elif [condition2]; then
    commands...
else
    commands...
fi
  • elif和else都可省略。
  • 支持多个if语句嵌套。

case语句

case的候选项可以使用bash的正则表达式,比如用*来实现c语言里default的功能。

case "$var" in

"$value1")
    commands...
    ;;

"$value2")
    commands...
    ;;

esac

以下代码取自ABS

while [ $# -gt 0 ]; do    # Until you run out of parameters . . .
    case "$1" in
        -d|--debug)
            DEBUG=1
            ;;
        -c|--conf)
            CONFFILE="$2"
            shift
            if [ ! -f $CONFFILE ]; then
                echo "Error: Supplied file doesn‘t exist!"
                exit $E_CONFFILE     # File not found error.
            fi
            ;;
    esac
    shift       # Check next set of parameters.
done

for循环

for arg in [list]
do
    commands...
done

例如

for i in $(seq 5); do
    echo $i
done

for循环的输出可以pipe到其他命令,例如

for f in $(ls); do
    echo $f
done | egrep "\.txt$"

while循环

while [condition]; do
    commands...
done

例如,从标准输入读10次并输出,break continue和c语言里是一样的效果。

i=0
limit=10
while read value; do
    echo $value
    let i++
    if [ $i -eq $limit ]; then
        break
    fi
done

还可以在条件表达式里使用(()),例如

(( i = 0 ))
(( limit = 10 ))
while (( i < limit )); do
    echo $i
    (( i++ ))
done
# 0
# 1
# ...
# 9

until循环

类似while循环,区别是当条件为false时执行,当条件为true时停止。

until [condition is true]; do
    commands...
done

函数

# 定义
function_name() {
    commands...
}

# 调用
function_name arg1 arg2 ... argN

在函数里用local定义的变量只能在函数体内使用。

函数参数

  • 函数体内,使用位置参数$1$2等来依此获取传入的参数。
  • 在函数体内使用shift命令对函数的参数也有效。
  • 使用$#来获取参数的个数。

函数返回值

  • 可以使用return来终止函数并返回数据。
  • 如果没有return语句,默认使用最后一条命令的退出状态来当作返回值。
  • 可以使用$?来获取函数的返回值。
  • 函数体内输入到标准输出的数据可以赋值给变量。

例子

一个比较脑惨的例子

show_params() {
    while [ "$#" -ne 0 ]; do
        echo $1
        shift
    done
    return 0
}

nums=$(show_params 1 2 3)
if [ "$?" -eq 0 ]; then
    echo "show_params function succeeded:" $nums
else
    echo "show_params function failed"
fi

# show_params function succeeded: 1 2 3

其他技巧

搜索子字符串

检查一个字符串$source是否包含某个字串$target,最方便的方法是

if [[ ${source} == *${target}* ]]; then
    ...
fi

其他工具

未完成

expr

字符串操作

seq

bc

sed

awk

参考资料

脚注

  1. type ‘[‘输出[ is a shell builtin,而不是/usr/bin/[,虽然作用都是一样的。
  2. 参考ABS 7.3. Other Comparison Operators中关于==的注释。
    [[ $a == z* ]] # True if $a starts with an "z" (pattern matching).
    [[ $a == "z*" ]] # True if $a is equal to z* (literal matching).
    [ $a == z* ] # File globbing and word splitting take place.
    [ "$a" == "z*" ] # True if $a is equal to z* (literal matching).
    
时间: 2025-01-08 23:59:09

Shell编程速查手册的相关文章

8086汇编指令速查手册

一.常用指令 二.算术运算指令 三.逻辑运算指令四.串指令 五.程序跳转指令------------------------------------------ 计算机寄存器分类简介: 32位CPU所含有的寄存器有:4个数据寄存器(EAX.EBX.ECX和EDX)2个变址和指针寄存器(ESI和EDI) 2个指针寄存器(ESP和EBP) 6个段寄存器(ES.CS.SS.DS.FS和GS)1个指令指针寄存器(EIP) 1个标志寄存器(EFlags) 1.数据寄存器数据寄存器主要用来保存操作数和运算结

awk速查手册

awk速查手册 score.txt cat score.txt Marry 2143 78 84 77 Jack 2321 66 78 45 Tom 2122 48 77 71 Mike 2537 87 97 95 Bob 2415 40 57 62 netstat.txt $cat netstat.txt Proto Recv-Q Send-Q Local-Address Foreign-Address State tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN t

25个有用和方便的 WordPress 速查手册

如果你是一个 WordPress 编码器或开发人员,下载一些方便的 WordPress 备忘单寻找你的工作然后你在正确的地方.我们已经列出了25个有用的和方便的 WordPress 速查手册.WordPress 备忘单后将帮助你发展你的 WordPress 主题和插件以及这些有助于搜索引擎优化你的博客.享受! ! 1. WP-CheatSheet 2. Complete WordPress Cheat Sheet 3. Cheat Sheet SEO for WordPress 4. WordP

《zw版&#183;Halcon-delphi系列原创教程》 zw版-Halcon常用函数Top100中文速查手册

<zw版·Halcon-delphi系列原创教程> zw版-Halcon常用函数Top100中文速查手册 Halcon函数库非常庞大,v11版有1900多个算子(函数). 这个Top版,对最常用的函数,做了中文说明,目前约250条,以后会逐步优化.增减. 目标是,类似常用英文单词500一样,做成<Halcon常用函数300条>.<halcon常用函数500条>等版本,方便大 家学习. 考虑到通用性,函数采用的是Halcon手册格式,没有转成delphi版,请大家注意.

Linux/Unix 系统分析命令速查手册

1.Hardware CPU information: cat /proc/cpuinfo 物理core个数: 统计core 逻辑CPU个数:统计processor Memory information: free -m 其中-+buffer是针对OS/App来说的. Disk information: fdisk -l df -h IO 性能: iostat -d -x -k 1 10 此命令属于sysstat包 观察await 平均io operation等待时间 观察%util 一秒中IO

R之data.table速查手册

R语言data.table速查手册 介绍 R中的data.table包提供了一个data.frame的高级版本,让你的程序做数据整型的运算速度大大的增加.data.table已经在金融,基因工程学等领域大放光彩.他尤其适合那些需要处理大型数据集(比如 1GB 到100GB)需要在内存中处理数据的人.不过这个包的一些符号并不是很容易掌握,因为这些操作方式在R中比较少见.这也是这篇文章的目的,为了给大家提供一个速查的手册. data.table的通用格式: DT[i, j, by],对于数据集DT,

Pandas速查手册中文版

本文翻译自文章: Pandas Cheat Sheet - Python for Data Science ,同时添加了部分注解. 对于数据科学家,无论是数据分析还是数据挖掘来说,Pandas是一个非常重要的Python包.它不仅提供了很多方法,使得数据处理非常简单,同时在数据处理速度上也做了很多优化,使得和Python内置方法相比时有了很大的优势. 如果你想学习Pandas,建议先看两个网站. (1)官网: Python Data Analysis Library (2)十分钟入门Pandas

HTML基础教程(17)——HTML 4.01速查手册

自 W3School 的 HTML 快速参考.可以打印它,以备日常使用. HTML Basic Document <html> <head> <title>Document name goes here</title> </head> <body> Visible text goes here </body> </html> Text Elements <p>This is a paragraph&

几个较好的SQL速查手册网址

微软 SQL server 数据库开发手册 数据库设计 Transact-SQL 速查手册 数据库设计 MySQL 中文参考手册速查 结构化查询语言 SQL 学习手册速查 转自:http://www.cnblogs.com/yencain/articles/1313465.html