Skip to content
ShenYj edited this page Mar 28, 2022 · 4 revisions

Shell

Shell 脚本的基本元素

  • 指定命令解读器 如:#!/bin/bash
  • 注释 :说明某些代码的功能
  • 可执行语句 :功能语句

一个.sh脚本执行的时候会先检查用户是否拥有该程序的执行权限

  • 无:”Permission denied“ 提示
  • 有:创建一个新的进程并执行语句

但是,Mac OSX 也是基于Unix 的 通常会同时安装多个Shell程序(sh,bash,csh等)

而不同的Shell程序语法有一定区别,到底使用哪个来执行代码系统无法正确判断,或者会默认调用执行导致执行结果并非我们期待的结果。

所以,Shell规定 “#!” 标识后面指定解释器的绝对路径 以方便创建指定解释器进程,解释并执行当前脚本。

Shell脚本中的注释和风格

Shell只支持单行注释 表示方法是#号

但是并不是说就只能用单行注释了 通过:« 后面写参数 ,但是要和结尾部分的参数想同 成对。

:<<xxx
echo "-----"
xxx

如何执行Shell程序

  • 授权,直接执行 chmod +x setup.sh”` 然后 ./setup.sh
  • 调用Shell脚本的解释器来执行 /bin/bash setup.sh
  • 通过source命令执行 source setup.sh

Shell程序的退出状态

每个命令都会返回一个退出状态码 退出状态码是一个整数,有效范围是0~255,通常情况下,成功的命令返回0,而不成功的命令返回非0值。

我们也可以根据逻辑判断 主动exit 错误码到shell

Shell脚本的参数

变量名称 说明
$0 当前脚本的文件名
$n 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2
$# 传递给脚本或函数的参数个数。
$* 传递给脚本或函数的所有参数。
$@ 传递给脚本或函数的所有参数。被双引号(" ")包含时,与 $* 稍有不同,下面将会讲到。
$? 上个命令的退出状态,或函数的返回值
$$ 当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID
$_ 保存之前执行的命令的最后一个参数
$! 后台运行的最后一个进程的 ID 号

e.g.

#!/usr/bin/env bash
echo "$@"

输出结果

Mac $ ./setup.sh a "b,c"
a b,c

Shell获取路径

pwd

pwd 代表的是Print Working Directory(打印当前目录)。如它的名字那样,pwd会打印出当前工作目录,或简单的来说就是当前用户所位于的目录。它会打印出以根目录 (/)为起点的完整目录名(绝对目录)。这条命令是一条shell内建命令,并且在大多数shell中都可以使用,如bash、Bourne shell,ksh、zsh等等

菜鸟教程:全面学习 pwd 命令

dirname-basename

  • dirname 可以获取一个文件所在的路径

    输出已经去除了尾部的”/”字符部分的名称;如果名称中不包含”/”,则显示”.”(表示当前目录)。

    有时候,我们需要知道当前执行的输出shell脚本的所在绝对路径,可以用dirname实现

    dirname "$PWD"
    /Users/shenyj/Documents/Code/MyProject/DashLine
  • basename

    它与dirname相反,是取得文件名称部分

    ❯ basename "$PWD"
    scripts

Shell中的括号

  • ${a}: 变量 a 的值,在不引起歧义的情况下可以省略大括号

  • $(cmd): 命令替换,和 cmd 效果相同

  • $()(exp): 增强括号的用法和 expr exp 效果相同,计算数学表达式 exp的数值,其中exp只要符合c语言的运算规则即可,甚至三目运算符和逻辑表达式都可以计算。可以省略$

    • e.g.

      for((i=0;i<5;i++>))
      # 如果不使用双括号
      for i in seq 0 4
      for i in {0..4}
      if (($i<5>))
      # 如果不使用双括号
      if [ $i -lt 5 ]
  • (cmd1;md2;cmd3): 新开一个子shell顺序执行命令cmd1cmd2cmd3,各命令之间用分号隔开,最后一个命令后可以没有分号

  • { cmd1;md2;cmd3;}: 在当前shell顺序执行命令cmd1cmd2cmd3,各命令之间用分号隔开,最后一个命令必须有分号,第一脚命令和左括号之间必须用空格隔开

  • shell里面的中括号(包括[][[]])可用于一些条件的测试:

    • 算数比较,比如一个变量是否为0: [ $var -eq 0 ]

    • 文件属性测试,比如一个文件是否存在: [ -e $var ]

    • 是否是目录, 比如: [ -d $var ]

    • [[]]: 字符串比较,增强括号用法,双括号中的表达式可以使用 &&||<>等语法,比如:

      # 比较两个字符串是否相同
      [[ $var1 = $var2 ]]
      if [[ $a != 1 && $a != 2 ]]
      # 如果不使用 [[]]
      if [ $a -ne 1] && [$a != 2 ]
      if [ $a -ne 1 -a $a != 2 ]

对于{}()而言,括号中的重定向符只影响该条命令,而括号外的重定向符影响到括号中的所有命令

Shell中的引号

首先,单引号和双引号,都是为了解决中间有空格的问题

因为空格在 shell 中作为一个典型的分隔符,比如stringl=this is astring,这样执行就会报错。为了避免这个问题,因此就产生了单引号和双引号,

他们的区别在于

  • 单引号将剥夺其中的所有字符的特殊含义
  • 双引号中的$(参数替换)和反引号(命令替换与$()作用一样)是例外。
  • 反引号的作用和 $(命令) 是一样的,但是反引号非常容易和单引号搞混,所以推荐使用 $(命令) 所以,晾着基本上没有什么区别,除非在内容中遇到了参数替换符$和命令替换符反引号

e.g.

  • 单引号

    echo '$PWD'
    $PWD
  • 双引号

    echo$PWD”
    “/Users/shenyj/Documents/Code/MyProject/DashLine/scripts”
  • 反引号

    echo `PWD`
    /Users/shenyj/Documents/Code/MyProject/DashLine/scripts

Getting Started

Social

Clone this wiki locally