1. shell

  对于一台计算机而言,其硬件受系统内核的控制,使用者想要控制计算机,就必须有与系统内核进行通讯的手段。而shell就是使用者与计算机进行通讯的手段之一。从命名上看,shell其实是相对于kernel(内核)而言,指系统与外界(使用者)进行接触的部分,一个提供系统功能给用户使用的软件,它接受来自用户的指令,然后调用相应的应用程序。
  为了满足不同的需求,shell提供了两种执行命令方式:

  • a. 交互式:解释并执行用户输入的命令或者自动地解释和执行预先设定好的一连串的命令。
  • b. 程序设计式:作为一种脚本语言,提供变量、控制结构和函数,再通过解释器解释并执行。
    Linux上常见的shell有sh、bash、ksh、tcsh等,不同解释器在某些语法的执行方面可能有些不同。通过查看/etc/shells文件就可以知道本系统所支持的shell解释器类型。如shells的文件内容如下:
    ryeshen@~$ cat /etc/shells
    /bin/sh
    /bin/bash
    /sbin/nologin
    /usr/bin/sh
    /usr/bin/bash
    /usr/sbin/nologin
    /bin/tcsh
    /bin/csh
    /bin/ksh
    /bin/zsh

      而linux默认是用的解释器是bash。在脚本头可以声明本脚本所使用的解释器,
    声明方式: #!/bin/bash

2. 变量

  • a. 赋值

    • 赋值方式:variable_name = variable_value
    • 等号两边不能有空格符;
    • 增加变量内容:PATH=”$PATH”:/home/bin
    • 取消变量:unset variable_name
    • 变量类型:可以使用declare [[-/+]aixr] [name[=value] …],其中-表示赋予变量属性,+表示去除变量属性,a-数组,i-整数,r-只读,x-环境变量
  • b. 自定义变量与环境变量

    • 使用“=”赋值得到的自定义变量,这个变量的作用域为当前shell进程。
    • 使用export命令可以声明一个环境变量,一个环境变量的作用域为当前shell进程及
      其shell子进程(subshell)。
    • 在启动shell进程的时候,shell会从文件中加载一些默认的环境变量到shell进程中,
      如HOME、PATH等。
    • 用env可以查看当前所有的环境变量,set则可以看所有的环境变量和自定义变量。
    • p.s. 关于子shell进程

      • i. 创建一个shell子进程的方式包括但不限于:

        • 使用&提交后台作业。后台作业于subshell中运行;
        • 使用管道。|左右的命令均在独立的subshell中运行;
        • 括号操作符。()中的命令在subshell中运行;
        • 执行外部脚本或程序。
      • ii. subshell可以继承shell父进程的属性包括:当前的工作目录、环境变量、标准输入输出和错误输出、所有已打开的文件描述符、忽略的信号。
      • iii. subshell对环境变量的修改对shell父进程不可见。
  • c. shell中的单引号、双引号和反引号

    • 双引号:保留$的变量扩展功能,使用变量时会$后的变量转变为变量的值。在双引号中可以使用转义符\将$转变为纯文本符号。使用双引号后不支持正则匹配。
    • 单引号:不保留特殊符号的功能,括号内内容仅作为纯文本进行使用。
      如:

      ryeshen@~$ echo "I am $name"
      I am someone
      ryeshen@~$ echo 'I am $name'
      I am $name
    • 反引号:引号内内容会被作为命令先被执行,命令的结果作为引号的输出。$()的效果与之相同
      如:

      ryeshen@~$ echo I am `pwd`
      I am /home/asl
      ryeshen@~$ echo I am $(pwd)
      I am /home/asl
    • p.s. 反引号与$()的一点区别

        — 参考自http://km.oa.com/articles/show/310289
      先来看几个例子:

      ryeshen@~$ echo `echo \$SHELL`
      /bin/bash
      ryeshen@~$ echo $(echo \$SHELL)
      $SHELL
      ryeshen@~$ echo `echo \\$SHELL`
      $SHELL
      ryeshen@~$ echo $(echo \\$SHELL)
      \/bin/bash
      ryeshen@~$ echo `echo \`
      >
      ryeshen@~$ echo $(echo \\)
      \

        参考的文章的解释是“反引号齐本身就对\进行了转义,保留了齐本身意思,如果我们想在反引号中起到\的特殊意义,我们必须使用2个\来进行表示”。
        对此我的理解是,在反引号中,\表示续行(见倒数第二个例子),\才表示转义符。而在$()中,\本身就起到转义符的效果。

      3. 数组

  • a. 赋值

     #shell脚本中#表示行注释
    array=(0 1 2 3 4)
    array[101]=101 #直接通过 数组名[下标] 就可以对其进行引用赋值。
    #如果下标不存在,自动添加新一个数组元素
    unset array[101] #使用unset清除指定值
    unset array #使用unset清除整个数组
  • b. 取值

    echo ${array[2]}      #使用下标获取值
    echo ${a[@]} #使用@或*获取数组所有值
    echo ${a[*]}

    输出结果:

    2
    0 1 2 3 4
    0 1 2 3 4
  • c. 截取

     #${数组名[@或*]:起始位置:长度}
    newArray=(${array[@]:1:3}) #先截取数组"1 2 3",再将截取到的数组赋给newArray
  • d. 遍历

    for a in ${arr[@]}
    do
    echo "$a"
    done
  • e. 拆分字符串到数组

    a="one,two,three,four"
    OLD_IFS="$IFS" #使用临时变量保存环境变量IFS的值
    IFS="," #给环境变量IFS赋值,这个值用来切割字符串
    arr=($a) #字符串切分
    IFS="$OLD_IFS" #还原IFS

4. 语法

  • a. if

    if语句的格式如下:

    if …; then

    elif …; then

    else

    fi

    注意格式中分号;的使用。
    if的判断语句中,方括号和逻辑运算符两边都必须有空格(“]”的右边除外)。

  • p.s. []必须有空格的原因

      “[“ 是linux系统中的指(试试whereis [),用法与test相同,但最后一个参数必须是 “]”。这也是为什么then前面要加分号”;”的原因。相似地可以推出,if后面可以接其他指令,利用其返回值进行判断,当返回值为0时if才判断为true
    如:

    ryeshen@~$ if echo "123"; then
    > echo "123"
    > fi
    123
    123
  • p.s. (),(()),[]和[[]]

    ( ): 1. 用于数组的初始化
      2. 指令群组(command group),即用括号将一组命令包括起
    来,这组命令共用一个shell子进程,因此可以分享自定义变量等。
    (( )): 相当于命令let,用于算数运算。举个例子:

    ryeshen@~$ ((a=1+1)); echo $a
    2
    ryeshen@~$ ((a=1+1)); echo $a
    2

    [ ]和[[ ]]的区别:
     如上所说,[其实是一个指令,因此使用判断中字符串时最好用双引号括住,
    且>、<必须改写成>和\<(>,<是重定向符)。
      另外,在使用&&和||时,必须写成 [ cond1 ] && [ cond2 ] 的形式。
    [[ ]]则是bash的关键字。可以直接使用>、<、&&、||,如[[ a>1 && b>2 ]]。
     [[ ]]中字符串未双引号括住的话,能进行正则表达式匹配。如:

    ryeshen@~$ [[ ab == a* ]] && echo "ok"
    ok

    if语句支持的运算符/操作符:(可以理解为是[指令的参数,就像rm -rf一样)

  • b. for

    for var in …; do
    do something
    done
    for (( cond1; cond2; cond3 )) do
    do something
    done

应用示例:

     #输出1 2 3 4 …… 10
for i in $(seq 10); do #这里是用seq指令生成了"1 2 3 …… 10"的字符串
echo $i;
done;
#判断输入的字符串是不是文件名
for file in $*; do # $*指从命令行读入的参数,如输入"test.sh a.xml b.txt c.pdf",则$*=(a.xml b.txt c.pdf)
if [ -f "$file" ]; then
echo "INFO: $file exists"
else
echo "ERROR: $file not exists"
fi
done;
  • p.s. 关于脚本的传入参数

    • $#是入参的个数,
    • $@和$*是当前所有的入参
    • $0是脚本的名字
    • $1是第一个入参,$2是第二个入参,以此类推
    • pp.s. $@和$*的区别
      • 不被双引号””括起来时,$@和$*一致。
      • 被双引号””括起来时:
        • “$*”表示“$0IFS$1IFS$2”。举个例子,设IFS为“-”,入参为“1 2 3”,则输出为“1-2-3”。
        • “$@”与$@相同
          ```
  • c. while和until

    while [ cond1 ] && { || } [ cond2 ] …; do
    do something
    done
    until [ cond1 ] && { || } [ cond2 ] …; do
    do somethingdone

    应用示例:

    # 逐行输出/etc/hosts文件内容
    while read line; do
    echo $line;
    done < /etc/hosts;
    # 这里能读入/etc/hosts,是因为<将文件重定向到read指令
  • d. case

    case var in
    pattern 1 )
    … ;;
    pattern 2 )
    … ;;
    *)
    … ;;
    esac
  • case行尾必须为单词“in”,每一个模式必须以右括号“)”结束。
  • ;; 表示命令序列结束。
  • pattern可以使用匹配符,如
    • a|b: a或者b
    • *:匹配任意长度的任意字符;
    • ?:匹配任意单个字符;
    • [-]:范围匹配
  • 另外提一下shfit,它可以将入参左移,即进行赋值:$1=$2;$2=$3;$3=$4……
    case可以与shfit结合使用,用于根据入参进行处理,举例如下:
    shell脚本test.sh:

    #!/bin/bash
    while [ $# -gt 0 ]; do
    case $1 in
    -a)
    shift; echo a-$1; shift;
    ;;
    -b|-d)
    shift; echo bd-$1; shift;
    ;;
    -c)
    shift; echo c-$1; shift;
    ;;
    *)
    echo unkown; shift;
    esac
    done

    输出:

    ryeshen@~$ ./test.sh -a 1 -c 2 -b 3 -d 3
    a-1
    c-2
    bd-3
    bd-3
  • e. function

    • 函数定义

      functionname()
      {
      do something
      }
      function func()
      {
      do something
      }
    • 函数调用
      函数必须先定义后使用。
      func param1 param2 ... # 函数内使用$#,$1等方式获取参数属性和参数,与脚本获取入参类似
  • 函数返回值
    func
    ret=$? #使用$?获取函数的执行结果
    ret=`func` #使用反单引号执行函数并将返回值赋值给变量
  • 函数变量
      + 脚本中定义的变量可在函数中使用
    + 函数中可用local关键字声明属于自己的,不被外部可见的局部变量

后记

  学习过shell的基础知识后,最大的感受是原以为是 shell脚本的特殊用法事实上是有规律可推理的。在此之前,虽然知道[]两边要加空格、使用while read $line;do……done < a.txt可以逐行读入文件等零碎的知识点,但只是知其然却不知其所以然。了解了shell的特殊符号的含义后,才发现这些东西并非只能靠死记硬背,而是有规则可循的。

shell基础知识总结的更多相关文章

  1. Linux shell基础知识(上)

    Linux shell基础知识(上) 目录 一.shell介绍 二.命令历史 三.命令补全和别名 四.通配符 五.输入输出重定向 六.管道符和作业控制 七.shell变量 八.环境变量配置文件 九.b ...

  2. Linux Shell 基础知识(一)

    1. 本文知识结构 2. shell 基础知识 2.1 shell 简单介绍 ​ GNU bash shell 能提供对 Linux 系统的交互式访问,一般来说,使用快捷键 Ctrl + Alt + ...

  3. Shell 基础知识和总结

    调试脚本 检查脚本语法错误 bash -n /path/to/some_script 调试执行 bash -x /path/to/some_script shell里的变量 本地变量:只对当前shel ...

  4. shell基础知识---与监听服务器长连接端口状态

    从未写过脚本我的最近接了俩脚本的需求,就在这分享一下我的我学到基础知识主要就四部分内容 一.变量 变量的定义 string='字符串' string="字符串" num=808st ...

  5. shell基础知识讲解

    第1章 shell基础 1.1 什么叫做shell编程 shell编程也叫做bash高级编程语法 1.2 常见的shell命令解释器 bash            redhat和centos使用 d ...

  6. shell基础知识

    Shell 学习基础 1.组合命令的符号 管道,将前面一个命令的结果作为后面一个命令的输入 分号,顺序执行用分号分割的命令 重定向,重定向包括三种:输入重定向.输出重定向.错误重定向,以7个不同的符号 ...

  7. shell从入门到精通进阶之一:Shell基础知识

    1.1 简介 Shell是一个C语言编写的脚本语言,它是用户与Linux的桥梁,用户输入命令交给Shell处理,Shell将相应的操作传递给内核(Kernel),内核把处理的结果输出给用户. 下面是处 ...

  8. Shell基础知识和编程规范

    一,Shell环境查看 1.1 查看系统Shell支持情况 [root@linux-node1 ~]# cat /etc/shells /bin/sh /bin/bash /sbin/nologin ...

  9. shell基础知识5-函数

    函数的定义 function fname(){ } 或者 function_name(){ } 对于简单的函数,甚至可以是这样做 fname() { statement; } 函数调用 直接写函数名即 ...

随机推荐

  1. FreeRTOS 中断优先级配置(重要)

    以下转载自安富莱电子: http://forum.armfly.com/forum.php NVIC 的全称是 Nested vectored interrupt controller,即嵌套向量中断 ...

  2. Unity3D学习(十一):关于UI销毁后图集仍然无法释放问题的解决办法

    前言 最近进行项目性能优化的时候发现的问题. 问题 从大厅进到单局的过程中,会经过选择英雄和加载两个流程,这两个流程对应的UI界面都会有一张几mb左右的贴图作为背景,在进入单局游戏后这两个UI已经销毁 ...

  3. MapReduce原理<转>

    江湖传说永流传:谷歌技术有"三宝",GFS.MapReduce和大表(BigTable)! 谷歌在03到06年间连续发表了三篇很有影响力的文章,分别是03年SOSP的GFS,04年 ...

  4. 深入分析DDR(转载)

    深入分析:我们为何需要DDR2内存技术 http://www.cnblogs.com/thx-bj/archive/2008/04/02/1134040.html 文/IT168评测室特约 Myddn ...

  5. hdu4675 GCD of Sequence 莫比乌斯+组合数学

    /** 题目:hdu4675 GCD of Sequence 链接:http://acm.hdu.edu.cn/showproblem.php?pid=4675 题意:给定n个数的a数组,以及m,k: ...

  6. nginx 的 autoindex on首页不显示的问题 按照下面几行要写上不然不行

    [root@test html]# vim ../conf/nginx.confworker_processes  1;events {    worker_connections  1024;}ht ...

  7. 微信小程序 - WapRequest.js

    文件位于 utils/WapRequest.js 封装了所有接口请求和wap站点的controller请求,代码示例 /** * 选择 洲 国家 * 无参数 */ WapRequest.prototy ...

  8. 编译FFmpeg for iOS

    2项依赖: gas-preprocessor(见附录:gas-preprocessor简介) yasm 1.2.0 如果要集成x264和fdk_aac,需要先编译x264和fdk_aac. Usage ...

  9. C++ 类的继承二(赋值兼容性原则)

    //赋值兼容性原则 #include<iostream> using namespace std; class PointA{ public: PointA(){ x = ; y = ; ...

  10. 嵌入式开发之davinci--- 8148/8168/8127 中的图像处理算法优化库vlib

    The Texas Instruments VLIB is an optimizedImage/Video Processing Functions Library for C programmers ...