Home Shell (1)
Post
Cancel

Shell (1)

[TOC]

阮一峰老师写的教程,这里做个精简笔记。

1 Shell 简述

Shell 是一个程序、命令解释器、工具箱,目的是为了能让用户跟系统内核交互。

Shell 主要种类:

  • Bourne Shell(sh)
  • Bourne Again shell(bash)
  • C Shell(csh)
  • TENEX C Shell(tcsh)
  • Korn shell(ksh)
  • Z Shell(zsh)
  • Friendly Interactive Shell(fish,这个不是 Mac 默认安装的,需要手动安装)

查看当前系统使用的 shell 、所有可用 shell、更改 shell。

1
2
3
$ echo $SHELL
$ cat /etc/shells
$ chsh -s /bin/xxx

2 命令参数格式和组合

Shell 使用空格(或 Tab 键)区分不同的参数,多余的空格会被忽略。

参数一般分为短参数和长参数两类,短参数多为单中划线+单个字母的形式 -x,长参数多为双中划线+单词的形式 --word。两类参数效果一样,短的常在人操作时使用,长的在脚本里用。

多条命令的执行:

  • ; 进行分隔的命令,后续命令不会关注前边的命令是否执行成功,只要前边的命令执行完成,后续的命令就会执行
  • && 或者 || 进行连接的命令,具备短路效应
1
2
3
4
5
6
# 前后命令都会执行
$ cat filelist.txt ; ls -l filelist.txt
# 只有 cat 成功 才会执行 ls
$ cat filelist.txt && ls -l filelist.txt
# 只有 foo 没有创建成功才会创建 bar
$ mkdir foo || mkdir bar

3 模式扩展(globbing)

Shell 接收到命令和参数后,首先进行模式扩展和通配符扩展(wildcard expansion),然后再执行命令。扩展的结果是由 Bash 负责的,与所要执行的命令无关。命令本身并不存在参数扩展,收到什么参数就原样执行。

模式扩展与正则表达式的关系是,模式扩展早于正则表达式出现,可以看作是原始的正则表达式。它的功能没有正则那么强大灵活,但是优点是简单和方便。

Bash 有八种扩展:

  • ~ 字符扩展

    • ~ 被扩展为当前用户目录
    • ~xxx 被扩展为用户 xxx 目录,如果用户不存在则不会扩展
    • ~+ 被扩展为当前目录,等价于 pwd
  • ? 字符扩展

    ? 是文件名扩展,如果文件不存在则不进行扩展,其匹配任意单个非空字符。

    1
    2
    3
    4
    5
    6
    7
    
    # 当前目录有 a.txt 文件,进行扩展
    $ echo ?.txt
    a.txt
      
    # 当前目录为空目录,不进行扩展
    $ echo ?.txt
    ?.txt
    
  • * 字符扩展

    * 是文件名扩展匹配任意字符包括空字符。

  • 方括号扩展

    方括号扩展是文件名扩展,文件存在时才会扩展。

    • [...],匹配其中任意一个字符
    • [^...][!...],匹配不在其中的字符
    • [start-end],起始写法
    • [!start-end],起始写法
  • 大括号扩展

    大括号扩展不是文件名扩展,它总会扩展成所有给定的值,而不管是否有对应的文件存在。

    • 大括号扩展 {...} 表示分别扩展成大括号里面的所有值,各个值之间使用逗号分隔。比如,{1,2,3} 扩展成 1 2 3

      1
      2
      3
      4
      5
      6
      7
      
      $ echo {1,2,3}
      1 2 3
      $ echo d{a,e,i,u,o}g
      dag deg dig dug dog
          
      $ echo Front-{A,B,C}-Back
      Front-A-Back Front-B-Back Front-C-Back
      
    • 逗号前后有空格,Bash 就会认为这不是大括号扩展,而是三个独立的参数。

      1
      2
      
      $ echo {1 , 2}
      {1 , 2}
      
    • 逗号前面可以没有值,表示扩展的第一项为空。

      1
      2
      
      $ echo a.log{,.bak}
      a.log a.log.bak
      
    • 可以嵌套。

      1
      2
      3
      4
      5
      
      $ echo {j{p,pe}g,png}
      jpg jpeg png
          
      $ echo a{A{1,2},B{3,4}}b
      aA1b aA2b aB3b aB4b
      
    • 大括号也可以与其他模式联用,并且总是先于其他模式进行扩展。

      1
      2
      3
      4
      5
      6
      
      # 先进行大括号扩展,然后进行*扩展,等同于执行两条echo命令
      $ echo /bin/{cat,b*}
      /bin/cat /bin/b2sum /bin/base32 /bin/base64 ... ...
          
      # 等同于
      $ echo /bin/cat;echo /bin/b*
      
    • {start..end},起始写法

    • {start..end..step},带间隔的起始写法

  • 变量扩展

    $ 开头或者 ${xxx} 视为变量,将其扩展成变量值。

  • 子命令扩展

    • $(...) 可以扩展成另一个命令的运行结果,该命令的所有输出都会作为返回值。老的语法,子命令放在反引号之中,也可以扩展成命令的运行结果。

      1
      2
      3
      4
      
      $ echo $(date)
      Tue Jan 28 00:01:13 CST 2020
      $ echo `date`
      Tue Jan 28 00:01:13 CST 2020
      
    • $(...) 也可以嵌套,比如 $(ls $(pwd))

  • 算术扩展

    $((...)) 可以扩展成整数运算的结果。

3.1 字符类

[[:class:]] 表示一个字符类,扩展成某一类特定字符之中的一个。常用的字符类如下。

  • [[:alnum:]]:匹配任意英文字母与数字
  • [[:alpha:]]:匹配任意英文字母
  • [[:blank:]]:空格和 Tab 键
  • [[:cntrl:]]:ASCII 码 0-31 的不可打印字符
  • [[:digit:]]:匹配任意数字 0-9
  • [[:graph:]]:A-Z、a-z、0-9 和标点符号
  • [[:lower:]]:匹配任意小写字母 a-z
  • [[:print:]]:ASCII 码 32-127 的可打印字符
  • [[:punct:]]:标点符号(除了 A-Z、a-z、0-9 的可打印字符)
  • [[:space:]]:空格、Tab、LF(10)、VT(11)、FF(12)、CR(13)
  • [[:upper:]]:匹配任意大写字母 A-Z
  • [[:xdigit:]]:16进制字符(A-F、a-f、0-9)
3.2 量词语法

量词语法用来控制模式匹配的次数。它只有在 Bash 的extglob参数打开的情况下才能使用,不过一般是默认打开的。

  • ?(pattern-list):匹配零个或一个模式。
  • *(pattern-list):匹配零个或多个模式。
  • +(pattern-list):匹配一个或多个模式。
  • @(pattern-list):只匹配一个模式。
  • !(pattern-list):匹配给定模式以外的任何内容。

4 echo 命令

echo 命令把跟在其后的输入原样输出出来。

1
2
$ echo hello world
hello world

内容放在引号内可以多行输出

1
2
$ echo "hello
world"
4.1 参数
  • -n 去掉末尾换行
1
2
$ echo -n hello world
hello world$
  • -e 解释引号内特殊字符(zsh 没有此参数,默认会解释特殊字符)
1
2
3
4
5
6
$ echo "Hello\nWorld"
Hello\nWorld

$ echo -e "Hello\nWorld"
Hello
World

5 type 命令

type 用来判断命令的类型,内置命令还是外部程序。

1
2
3
4
$ type echo
echo is a shell builtin
$ type ls
ls is hashed (/bin/ls)

-t 参数返回命令类型,别名(alias),关键词(keyword),函数(function),内置命令(builtin)和文件(file)。

6 标准输入、输出、错误重定向

在 shell 中每个进程都与三个系统文件相关联:标准输入 stdin、标准输出 stdout、标准错误 stderr,三个系统文件的文件描述符分别为0、1、2。因此有时遇到重定向时,需要根据数字进行判断。譬如:

  • 2>&1 表示将标准错误重定向到标准输出
  • xxx 2 > /dev/null 表示丢弃标准错误

License:署名-相同方式共享 3.0

This post is licensed under CC BY 4.0 by the author.