Shell历史

  • Shell的功用是分解用户的命令,用户输入一条命令,Shell就分解实施一条,那条办法叫做交互式(interactive),Shell还有一种执行命令的方法叫做批处理(batch),用户优先写多个Shell脚本(script),其中有不可胜数条命令,让Shell一回把那些命令执行完,而不必一条条地敲命令。Shell脚本和编程语言相似,也有变量和流程控制语句,但Shell脚本是分解施行的,不须求编译,Shell程序从剧本中一行一行读取并施行那一个命令,也等于三个用户把脚本中的命令一行一行敲到Shell指示符下执行。
  • 出于历史原因,UNIX系统上有很各个Shell:

    • 1、sh(Bourne Shell):由SteveBourne开发,各个UNIX系统都配有sh。
    • 2、csh(C Shell):由Bill Joy开发,随BSD
      UNIX公布,它的流水线控制语句很象C语言,接济广大Bourne
      Shell把不襄助的效益:作业控制,命令历史,命令行编辑。
    • 3、ksh(Korn Shell):由DavidKorn开发,向后非凡sh的作用,并且添加了csh引入的新效用,是时下无数UNIX系统标准配置的Shell,在那一个体系上/bin/sh往往是指向/bin/ksh的标记链接。
    • 4、tcsh(TENEX C
      Shell):是csh的增长版本,引入了命令补全等职能,在FreeBSD、MacOS
      X等连串上代表了csh。
    • 5、bash(Bourne Again
      Shell):由GNU开发的Shell,首要目的是与POSIX标准保持一致,同时全职对sh的匹配,bash从csh和ksh借鉴了不少职能,是各样Linux发行版标准配置的Shell,在Linux系统上/bin/sh往往是指向/bin/bash和标志链接。尽管那样,bash和sh如故有许多不比的,一方面,bash增加了有些命令和参数,另一方面,bash并不完全和sh包容,有个别行为并不一样,所以bash必要效法sh的作为:当大家经过sh这一个顺序名运行bash时,bash可以装作本人是sh,不认伸张的指令,并且作为与sh保持一致。

        $ cat /etc/passwd
        root:x:0:0:root:/root:/bin/zsh
        daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
        bin:x:2:2:bin:/bin:/usr/sbin/nologin
        sys:x:3:3:sys:/dev:/usr/sbin/nologin
        sync:x:4:65534:sync:/bin:/bin/sync
      
  • 用户在命令行输入指令后,一般景观下Shell会fork并exec该命令,不过Shell的内建命令例外,执行内建命令相当于调用Shell进度中的1个函数,并不创立新的经过。在此之前学过的cd、alias、umask、exit等一声令下即是内建命令,凡是用which命令查不到程序文件所在地点的命令都以内建命令,内建命令没有单独的man手册,要在man手册中查阅内建命令,应该履行

      $ man bash-builtins
    
  • 如export、shift、if、eval、[、for、while等等。内建命令尽管不成立新的进度,但也会有Exit
    Status,平常也用0表示成功非零代表失利,就算内建命令不创造新的历程,但实践达成后也会有二个状态码,也足以用特殊变量$?读出。

Shell历史

  • Shell的功能是解说用户的吩咐,用户输入一条命令,Shell就解释施行一条,那条措施叫做交互式(interactive),Shell还有一种执行命令的措施叫做批处理(batch),用户优先写一个Shell脚本(script),其中有过多条命令,让Shell一回把这几个命令执行完,而不必一条条地敲命令。Shell脚本和编程语言相似,也有变量和流程控制语句,但Shell脚本是解说实施的,不须要编译,Shell程序从剧本中一行一行读取并履行这个命令,也等于3个用户把脚本中的命令一行一行敲到Shell提醒符下执行。
  • 由于历史原因,UNIX系统上有很八种Shell:

    • 1、sh(Bourne Shell):由SteveBourne开发,各样UNIX系统都配有sh。
    • 2、csh(C Shell):由Bill Joy开发,随BSD
      UNIX发表,它的流水线控制语句很象C语言,支持广大Bourne
      Shell把不帮助的效果:作业控制,命令历史,命令行编辑。
    • 3、ksh(Korn Shell):由大卫Korn开发,向后出色sh的机能,并且添加了csh引入的新效率,是目前广大UNIX系统标准配置的Shell,在这几个系统上/bin/sh往往是指向/bin/ksh的符号链接。
    • 4、tcsh(TENEX C
      Shell):是csh的滋长版本,引入了指令补全等功能,在FreeBSD、MacOS
      X等系统上代表了csh。
    • 5、bash(Bourne Again
      Shell):由GNU开发的Shell,首要对象是与POSIX标准保持一致,同时专职对sh的匹配,bash从csh和ksh借鉴了许多效率,是各样Linux发行版标准配置的Shell,在Linux系统上/bin/sh往往是指向/bin/bash和标志链接。纵然那样,bash和sh依然有广大例外的,一方面,bash伸张了一些限令和参数,另一方面,bash并不完全和sh包容,有个别行为并不相同等,所以bash要求效法sh的一坐一起:当大家透过sh这些顺序名运营bash时,bash可以装作本人是sh,不认伸张的授命,并且作为与sh保持一致。

      $ cat /etc/passwd
      root:x:0:0:root:/root:/bin/zsh
      daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
      bin:x:2:2:bin:/bin:/usr/sbin/nologin
      sys:x:3:3:sys:/dev:/usr/sbin/nologin
      sync:x:4:65534:sync:/bin:/bin/sync
      
  • 用户在命令行输入指令后,一般意况下Shell会fork并exec该命令,然而Shell的内建命令例外,执行内建命令也就是调用Shell进程中的多个函数,并不创建新的进度。在此以前学过的cd、alias、umask、exit等一声令下即是内建命令,凡是用which命令查不到程序文件所在地点的授命都以内建命令,内建命令没有单身的man手册,要在man手册中查阅内建命令,应该进行

    $ man bash-builtins
    
  • 如export、shift、if、eval、[、for、while等等。内建命令尽管不创制新的经过,但也会有Exit
    Status,平常也用0表示成功非零代表战败,即便内建命令不创建新的进程,但推行落成后也会有三个状态码,也可以用新鲜变量$?读出。

Shell编程,linuxshell编程

Author: Shixiang Wang

实践脚本

  • 编辑3个总结的脚本test.sh:

      #! /bin/sh
      cd ..
      ls
    
  • Shell脚本中用#意味着注释,相当于C语言的//注释。但万一#身处第一行伊始,并且是#!(称为Shebang)则不一致,它象征该脚本使用后边指定的演讲器/bin/sh解释执行。假若把这几个本子文件加上可实施权限然后实施:

      $ chmod a+x test.sh
      $ ./test.sh
    
  • Shell会fork五个子经过并调用exec执行./test.sh那几个程序,exec系统调用应该把子进度的代码段替换成./test.sh先后的代码段,并从它的_start开班推行。然则test.sh是个公文文件,根本未曾代码段和_start函数,如何是好吧?其实exec还有其余一种体制,如若要实施的是三个文本文件,并且第一行用Shebang指定明白释器,则用解释程序的代码段替换当前进程,并且从解释器的_start始发实施,而那一个文件文件被当作命令行参数传给解释器。因而,执行上述脚本约等于履行顺序

      $ /bin/sh ./test.sh
    
  • 以这种措施举办不必要test.sh文件可实施权限。

  • 比方将下令行下输入的下令用()括号括起来,那么也会fork出1个子Shell执行小括号中的命令,一行中得以输入由支行;隔开的多个命令,比如:

      $ (cd ..; ls -l)
    
  • 和方面三种艺术执行Shell脚本的功力是平等的,cd ..命令改变的是子Shell的PWD,而不影响到交互式Shell。

      $ cd ..; ls -l
    
  • 则区其他效益,cd ..一声令下是直接在交互式Shell下举办的,改变交互式Shell的PWD,可是那种措施约等于如此进行Shell脚本:

      $ source ./test.sh
      或者
      $ . ./test.sh
    
  • source可能.命令是Shell的内建命令,那种办法也不会创制子Shell,而是直接在交互式Shell下逐行执行脚本中的命令。

履行脚本

  • 编纂三个简约的脚本test.sh:

    #! /bin/sh
    cd ..
    ls
    
  • Shell脚本中用#代表注释,相当于C语言的//注释。但只要#置身第一行初阶,并且是#!(称为Shebang)则差距,它意味着该脚本使用后边指定的解说器/bin/sh解释执行。即使把这一个剧本文件加上可举办权限然后实施:

    $ chmod a+x test.sh
    $ ./test.sh
    
  • Shell会fork三个子历程并调用exec执行./test.sh其一顺序,exec系统调用应该把子进度的代码段替换成./test.sh先后的代码段,并从它的_start初叶执行。然则test.sh是个公文文件,根本未曾代码段和_start函数,如何是好吧?其实exec还有其余一种体制,若是要实施的是多个文书文件,并且第一行用Shebang指定精通释器,则用解释程序的代码段替换当前经过,并且从解释器的_start起来举行,而以此文件文件被当作命令行参数传给解释器。由此,执行上述脚本相当于实践顺序

    $ /bin/sh ./test.sh
    
  • 以那种措施执行不须要test.sh文件可进行权限。

  • 即使将下令行下输入的指令用()括号括起来,那么也会fork出二个子Shell执行小括号中的命令,一行中可以输入由支行;隔开的两个命令,比如:

    $ (cd ..; ls -l)
    
  • 和地点三种方法执行Shell脚本的效劳是相同的,cd ..命令改变的是子Shell的PWD,而不影响到交互式Shell。

    $ cd ..; ls -l
    
  • 则差别的意义,cd ..指令是直接在交互式Shell下实施的,改变交互式Shell的PWD,然则这种措施相当于如此举行Shell脚本:

    $ source ./test.sh
    或者
    $ . ./test.sh
    
  • source恐怕.命令是Shell的内建命令,那种办法也不会创制子Shell,而是一向在交互式Shell下逐行执行脚本中的命令。

Shell历史

  • Shell的法力是分解用户的通令,用户输入一条命令,Shell就表达施行一条,那条办法叫做交互式(interactive),Shell还有一种执行命令的艺术叫做批处理(batch),用户优先写1个Shell脚本(script),其中有不少条命令,让Shell一回把那么些命令执行完,而不必一条条地敲命令。Shell脚本和编程语言相似,也有变量和流程控制语句,但Shell脚本是表达实施的,不需求编译,Shell程序从剧本中一行一行读取并履行那些命令,也等于二个用户把脚本中的命令一行一行敲到Shell指示符下执行。
  • 出于历史原因,UNIX系统上有很种种Shell:

    • 1、sh(Bourne Shell):由SteveBourne开发,各样UNIX系统都配有sh。
    • 2、csh(C Shell):由Bill Joy开发,随BSD
      UNIX公布,它的流程控制语句很象C语言,扶助广大Bourne
      Shell把不支持的功力:作业控制,命令历史,命令行编辑。
    • 3、ksh(Korn Shell):由大卫Korn开发,向后分外sh的效益,并且添加了csh引入的新效能,是时下无数UNIX系统标准配置的Shell,在那几个系统上/bin/sh往往是指向/bin/ksh的标记链接。
    • 4、tcsh(TENEX C
      Shell):是csh的拉长版本,引入了指令补全等效果,在FreeBSD、MacOS
      X等系统上代表了csh。
    • 5、bash(Bourne Again
      Shell):由GNU开发的Shell,主要目的是与POSIX标准保持一致,同时兼顾对sh的卓绝,bash从csh和ksh借鉴了许多效应,是各类Linux发行版标准配置的Shell,在Linux系统上/bin/sh往往是指向/bin/bash和标记链接。纵然如此,bash和sh依旧有广大不比的,一方面,bash增加了部分下令和参数,另一方面,bash并不完全和sh包容,某个行为并不相同,所以bash须求效法sh的表现:当咱们因此sh那一个顺序名运行bash时,bash可以伪装自身是sh,不认扩张的命令,并且作为与sh保持一致。

      $ cat /etc/passwd
      root:x:0:0:root:/root:/bin/zsh
      daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
      bin:x:2:2:bin:/bin:/usr/sbin/nologin
      sys:x:3:3:sys:/dev:/usr/sbin/nologin
      sync:x:4:65534:sync:/bin:/bin/sync
      
  • 用户在命令行输入指令后,一般情形下Shell会fork并exec该命令,可是Shell的内建命令例外,执行内建命令相当于调用Shell进度中的3个函数,并不创立新的进程。在此从前学过的cd、alias、umask、exit等一声令下即是内建命令,凡是用which命令查不到程序文件所在地点的下令都是内建命令,内建命令没有单身的man手册,要在man手册中查阅内建命令,应该举行

    $ man bash-builtins
    
  • 如export、shift、if、eval、[、for、while等等。内建命令固然不成立新的经过,但也会有Exit
    Status,平时也用0表示成功非零代表失败,纵然内建命令不创立新的长河,但实践已毕后也会有一个状态码,也可以用万分变量$?读出。

[TOC]

主导语法

主干语法

施行脚本

  • 编写多少个大约的脚本test.sh:

    #! /bin/sh
    cd ..
    ls
    
  • Shell脚本中用#代表注释,相当于C语言的//注释。但倘使#位居第一行开头,并且是#!(称为Shebang)则差距,它意味着该脚本使用前边指定的表达器/bin/sh解释执行。要是把那一个剧本文件加上可实施权限然后实施:

    $ chmod a+x test.sh
    $ ./test.sh
    
  • Shell会fork2个子进程并调用exec执行./test.sh以此程序,exec系统调用应该把子进度的代码段替换成./test.sh先后的代码段,并从它的_start千帆竞发实践。但是test.sh是个公文文件,根本没有代码段和_start函数,如何是好呢?其实exec还有其余一种体制,如果要实践的是一个文本文件,并且第一行用Shebang指定通晓释器,则用解释程序的代码段替换当前历程,并且从解释器的_start起施夷光行,而以此文件文件被当作命令行参数传给解释器。因而,执行上述脚本约等于履行顺序

    $ /bin/sh ./test.sh
    
  • 以那种方法实施不需要test.sh文件可进行权限。

  • 一旦将指令行下输入的一声令下用()括号括起来,那么也会fork出二个子Shell执行小括号中的命令,一行中得以输入由支行;隔开的多个命令,比如:

    $ (cd ..; ls -l)
    
  • 和上面三种办法执行Shell脚本的成效是同一的,cd ..指令改变的是子Shell的PWD,而不影响到交互式Shell。

    $ cd ..; ls -l
    
  • 则不相同的效应,cd ..指令是直接在交互式Shell下实施的,改变交互式Shell的PWD,然则那种办法约等于那样实践Shell脚本:

    $ source ./test.sh
    或者
    $ . ./test.sh
    
  • source大概.命令是Shell的内建命令,那种办法也不会创设子Shell,而是间接在交互式Shell下逐行执行脚本中的命令。

grep

变量

  • 依据惯例,Shell变量平常由字母加下划线开头,由任意长度的假名、数字、下划线组成。有两种类型的Shell变量:
    • 一,环境变量
      • 环境变量可以从父进度传给子进程,因些Shell进度的环境变量可以从目前Shell进度传给fork出来的子进度。用printenv指令能够来得当前Shell的环境变量。
    • 贰,本地变量
      • 只存在于方今Shell进度,用set指令可以显得当前Shell进度中定义的富有变量(包含当地变量和环境变量)和函数。
  • 环境变量是任何进程都有些概念,而本地变量是Shell特有的概念。在Shell中,环境变量和本土变量的定义和用法相似。在Shell中定义或赋值二个变量:

      $ VARNAME=value
    
  • 注意等号两边都无法有空格,否则会被Shell解释成命令行参数。

  • 一个变量定义后仅设有于当下Shell进度,它是本土变量,用export命令可以把地点变量导出为环境变量,定义和导出环境变量平日可以一步成功:

      $ export VARNAME=value
    
  • 也足以分两步成功:

      $ VARNAME=value
      $ export VARNAME
    
  • 用unset命令能够删除已定义的环境变量或本地变量。

      $ unset VARNAME
    
  • 假若二个变量叫做VA奔驰G级NAME,用’VAKugaNAME’可以代表它的值,在不引起歧义的景观下也得以用VA普拉多NAME表示它的值。通过以下的例证相比这三种表示法的不等:

      $ echo $SHELL
    
  • 小心,在概念变量时毫无”‘”,取变量值时要用。和C语言不相同的是,Shell变量不要求领悟概念类型,事实上Shell变量的值都是字符串,比如我们定义VA景逸SUV=45,其实VAENCORE的值是字符串45而非整数。Shell变量不须求先定义后使用,若是二个从未概念的变量取值,则值为空字符串。

变量

  • 听从规矩,Shell变量经常由字母加下划线开首,由任意长度的假名、数字、下划线组成。有两连串型的Shell变量:
    • 1、环境变量
      • 环境变量可以从父进度传给子进度,因些Shell过程的环境变量可以从眼下Shell进程传给fork出来的子进度。用printenv指令可以展现当前Shell的环境变量。
    • 2、本地变量
      • 只设有于近日Shell进程,用set指令可以来得当前Shell进度中定义的兼具变量(包罗地面变量和环境变量)和函数。
  • 环境变量是其他进程都有的概念,而本土变量是Shell特有的定义。在Shell中,环境变量和当地变量的概念和用法相似。在Shell中定义或赋值贰个变量:

    $ VARNAME=value
    
  • 留意等号两边都不可以有空格,否则会被Shell解释成命令行参数。

  • 二个变量定义后仅存在于近年来Shell进度,它是本土变量,用export命令可以把地面变量导出为环境变量,定义和导出环境变量平常能够一步成功:

    $ export VARNAME=value
    
  • 也得以分两步成功:

    $ VARNAME=value
    $ export VARNAME
    
  • 用unset命令可以删除已定义的环境变量或地面变量。

    $ unset VARNAME
    
  • 只要3个变量叫做VALANDNAME,用’VALANDNAME’能够表示它的值,在不引起歧义的状态下也得以用VARubiconNAME表示它的值。通过以下的例证相比这二种表示法的两样:

    $ echo $SHELL
    
  • 小心,在概念变量时不要”‘”,取变量值时要用。和C语言差其余是,Shell变量不需求通晓概念类型,事实上Shell变量的值都以字符串,比如大家定义VA奇骏=45,其实VA福特Explorer的值是字符串45而非整数。Shell变量不要求先定义后使用,假使一个从未有过定义的变量取值,则值为空字符串。

主导语法

grep的主导用法

grep命令是匡助正则表明式的3个多用途文本搜索工具,一般格式为

grep 选项 模式 文件

选项 意义
-c 只输出匹配行的数量
-i 搜索时忽略大小写
-h 查询多文件时不显示文件名
-l 只列出符合匹配的文件名,而不列出具体的匹配行
-n 列出所有的匹配行,并显示行号
-s 不显示不存在或无匹配文本的错误信息
-v 显示不包含匹配文本的所有行
-w 匹配整词
-x 匹配正行
-r 递归搜索,不仅搜索当前目录,而且搜索子目录
-q 禁止输出任何结果,以退出状态表示搜索是否成功
-b 打印匹配行距文件头部的偏移量,以字节为单位
-o 与-b选项结合使用,打印匹配的词距文件头部的偏移量,以字节为单位
-E 支持扩展的正则表达式
-F 不支持正则表达式,按照字符串的字面意思进行匹配

grep命令的情势特别灵活,可以是字符串,也能够是变量,还足以是正则表明式。注意,无论形式是何种格局,只要格局中包括空格,就须求运用双引号将方式引起来。

文件名代换(Globbing)

  • 这么些用于匹配的字符称为通配符(魏尔德card),如:*?[]Shell编程。,具体如下:

    • *匹配0个或五个随机字符
    • ?相当两个专擅字符
    • [多少字符]卓越方括号中任意一个字符的两次出现

        $ ls /dev/ttyS*
        $ ls ch0?.doc
        $ ls ch0[0-2].doc
        $ ls ch[012][0-9].doc
      
    • 在意,Globbing所匹配的公文名是由Shell展开的,相当于说在参数还没传给程序从前曾经拓展了,比如上述ls ch0[012].doc一声令下,即使当前目录下有ch00.doc和ch02.doc,则传给ls命令的参数实际上是那八个文件名,而不是二个匹配字符串。

文件名代换(Globbing)

  • 那些用于匹配的字符称为通配符(魏尔德card),如:*?[],具体如下:

    • *匹配0个或三个随机字符
    • ?分外一个随意字符
    • [多少字符]极度方括号中自由两个字符的五次出现

      $ ls /dev/ttyS*
      $ ls ch0?.doc
      $ ls ch0[0-2].doc
      $ ls ch[012][0-9].doc
      
    • 在意,Globbing所匹配的公文名是由Shell展开的,约等于说在参数还没传给程序以前曾经开展了,比如上述ls ch0[012].doc指令,若是当前目录下有ch00.doc和ch02.doc,则传给ls命令的参数实际上是这多少个文件名,而不是一个匹配字符串。

变量

  • 根据常规,Shell变量平时由字母加下划线开首,由任意长度的字母、数字、下划线组成。有三种档次的Shell变量:

    • 一,环境变量
      • 环境变量可以从父进度传给子进度,因些Shell进度的环境变量可以从当前Shell进程传给fork出来的子进度。用printenv指令可以显示当前Shell的环境变量。
    • 二,本地变量
      • 只存在于近年来Shell过程,用set指令可以显得当前Shell进度中定义的富有变量(包含当地变量和环境变量)和函数。
  • 环境变量是其余进度都某个概念,而当地变量是Shell特有的概念。在Shell中,环境变量和地点变量的定义和用法相似。在Shell中定义或赋值3个变量:

    $ VARNAME=value
    
  • 注意等号两边都不能有空格,否则会被Shell解释成命令行参数。

  • 二个变量定义后仅设有于当下Shell进度,它是地点变量,用export命令可以把地点变量导出为环境变量,定义和导出环境变量平常可以一步成功:

    $ export VARNAME=value
    
  • 也足以分两步成功:

    $ VARNAME=value
    $ export VARNAME
    
  • 用unset命令能够删除已定义的环境变量或当地变量。

    $ unset VARNAME
    
  • 假定一个变量叫做VACRUISERNAME,用’VALX570NAME’可以表示它的值,在不引起歧义的状态下也足以用VATiggoNAME表示它的值。通过以下的事例相比那两种表示法的不等:

    $ echo $SHELL
    
  • 在意,在概念变量时不用”‘”,取变量值时要用。和C语言不一样的是,Shell变量不须要鲜明定义类型,事实上Shell变量的值都是字符串,比如我们定义VA瑞虎=45,其实VA奇骏的值是字符串45而非整数。Shell变量不必要先定义后采纳,如若多少个尚未概念的变量取值,则值为空字符串。

grep与正则表明式

  1. 协作行首,用元字符^

  1. 安装大小写,用-i

  2. 同盟重复字符,用., *

  3. 转义符,用\

  4. POSIX字符类

    类名 意义
    [:upper:] 表示大写字母[A~Z]
    [:lower:] 表示小写字母[a~z]
    [:digit:] 表示阿拉伯数字[0~9]
    [:alnum:] 表示大小写字母和阿拉伯数字
    [:space:] 表示空格键和TAB键
    [:alpha:] 表示大小写字母
    [:cntrl:] 表示Ctrl
    [:graph:]或[:print:] 表示ASCII码
    [:xdigit:] 表示16进制数字[09AFa~f]
  5. 规范匹配:用\<\>

  6. 或字符,grep要求添加-E选项才能支撑它,用|表示

指令代换

  • 由“`”反引号括起来的也是一条命令,Shell先实施该命令,然后将出口结果即时期换到当前下令行中。例如定义三个变量存放date命令的出口:

      $ DATE=`date`
      $ echo $DATE
    
  • 命令代换也得以用$()表示:

      $ DATE=$(date)
    

一声令下代换

  • 由“`”反引号括起来的也是一条命令,Shell先实施该命令,然后将出口结果立即代换来当前下令行中。例如定义贰个变量存放date命令的出口:

    $ DATE=`date`
    $ echo $DATE
    
  • 一声令下代换也足以用$()表示:

    $ DATE=$(date)
    

文件名代换(Globbing)

  • 这一个用于匹配的字符称为通配符(魏尔德card),如:*?[],具体如下:

    • *匹配0个或七个随机字符
    • ?匹配壹个自由字符
    • [多少字符]匹配方括号中自由1个字符的五次面世

      $ ls /dev/ttyS*
      $ ls ch0?.doc
      $ ls ch0[0-2].doc
      $ ls ch[012][0-9].doc
      
    • 在意,Globbing所匹配的文本名是由Shell展开的,约等于说在参数还没传给程序以前曾经开展了,比如上述ls ch0[012].doc指令,假如当前目录下有ch00.doc和ch02.doc,则传给ls命令的参数实际上是那七个文件名,而不是一个匹配字符串。

grep命令族

grep: 标准grep命令

egrep: 扩张grep命令,帮衬中央和进展正则表明式

fgrep: 迅速grep命令,不资助正则表达式


算术代换

  • 行使$(()),用于算术总计,(())中的Shell变量取值将转换成整数,同样含义的$[]等价,例如:

      $ VAR=45
      $ echo $(($VAR+3))   等价于 echo $[VAR+3]或$[$VAR+3]
    
  • $(())中不得不用+-*/和()运算符,并且不得不做整数运算。

  • $[base#n],其中base表示进制,n依照base进制解释,前边再运算数,按十进制解释。

      $ echo $[2#10+11]
      $ echo $[8#10+11]
      $ echo $[16#10+11]
    

算术代换

  • 拔取$(()),用于算术总计,(())中的Shell变量取值将转换成整数,同样含义的$[]等价,例如:

    $ VAR=45
    $ echo $(($VAR+3))   等价于 echo $[VAR+3]或$[$VAR+3]
    
  • $(())中不得不用+-*/和()运算符,并且不得不做整数运算。

  • $[base#n],其中base表示进制,n依据base进制解释,前边再运算数,按十进制解释。

    $ echo $[2#10+11]
    $ echo $[8#10+11]
    $ echo $[16#10+11]
    

指令代换

  • 由“`”反引号括起来的也是一条命令,Shell先举办该命令,然后将出口结果即时期换来当前下令行中。例如定义二个变量存放date命令的出口:

    $ DATE=`date`
    $ echo $DATE
    
  • 指令代换也足以用$()表示:

    $ DATE=$(date)
    

sed命令

sed是1个非交互式文本编辑器,它可对文件文件和正规输入举办编制,标准输入可以是缘于键盘输入、文件重定向、字符串、变量,甚至来自管道的公文。sed适用于以下三中场馆:

  • 编辑绝对交互式文本编辑器而言太大的文件。
  • 编制命令太复杂,在交互式文本编辑器中难以输入的景况。
  • 对文本扫描三回,不过必要实践多个编辑函数的事态。

转义字符

  • 和C语言类似,\在Shell中被看成转义字符,用于去除紧跟其后的单个字符的奇异意义(回车除外),换句话说,紧跟其后的字符取字面值。例如:

      $ echo $SHELL
      /bin/bash
      $ echo \$SHELL
      $SHELL
      $ echo \\
      \
    
  • 比如说创设一个文书名为”$ $”的文书($间含有空格),可以那样:

      $ touch \$\ \$
    
  • 还有一个字符即便不抱有非同平日含义,可是要用它做文件名也很麻烦,就是-号。若是要开创2个文书名以-号起先的文书,那样是不科学的:

      $ touch -hello
      touch:无效选项 -- e
      Try 'touch --help' for more information.
    
  • 尽管加上\转义也如故报错:

      $ touch \-hello
      touch:无效选项 -- e
      Try 'touch --help' for more information.
    
  • 因为种种UNIX命令都把-号开关的命令行参数作为命令的选项,而不会作为文件名。,若是非要处理以-号开始的公文名,或许有三种方式:

      $ touch ./-hello
      或者
      $ touch -- -hello
    

转义字符

  • 和C语言类似,\在Shell中被当作转义字符,用于去除紧跟其后的单个字符的非正规意义(回车除外),换句话说,紧跟其后的字符取字面值。例如:

    $ echo $SHELL
    /bin/bash
    $ echo \$SHELL
    $SHELL
    $ echo \\
    \
    
  • 比如说创立一个文书名为”$ $”的公文($间含有空格),可以如此:

    $ touch \$\ \$
    
  • 再有1个字符纵然不富有特殊意义,不过要用它做文件名也很费力,就是-号。假设要创建2个文件名以-号起先的文本,那样是不得法的:

    $ touch -hello
    touch:无效选项 -- e
    Try 'touch --help' for more information.
    
  • 纵使加上\转义也依然报错:

    $ touch \-hello
    touch:无效选项 -- e
    Try 'touch --help' for more information.
    
  • 因为种种UNIX命令都把-号开关的命令行参数作为命令的选项,而不会作为文件名。,借使非要处理以-号开首的文件名,或者有三种办法:

    $ touch ./-hello
    或者
    $ touch -- -hello
    

算术代换

  • 行使$(()),用于算术统计,(())中的Shell变量取值将转换成整数,同样含义的$[]等价,例如:

    $ VAR=45
    $ echo $(($VAR+3))   等价于 echo $[VAR+3]或$[$VAR+3]
    
  • $(())中不得不用+-*/和()运算符,并且不得不做整数运算。

  • $[base#n],其中base表示进制,n根据base进制解释,后边再运算数,按十进制解释。

    $ echo $[2#10+11]
    $ echo $[8#10+11]
    $ echo $[16#10+11]
    

大旨用法

sed只是对缓冲区炎黄始文件的副本举办编辑,并不编辑原始文本。假设急需保留文件改动的始末,须要将出口重定向到另2个文本。

调用sed有三种办法,一种为Shell命令行形式,此外三种是将sed一声令下写入脚本文件,然后实施该脚本文件。

  1. 在Shell命令行输入指令调用sed,格式为sed [选项] 'sed命令' 输入文件
  2. sed命令插入脚本文件后,然后经过sed命令调用它,格式为sed [选项] -f sed 脚本文件 输入文件
  3. sed一声令下插入脚本文件后,最常用的格局是设置该脚本文件为可以实施,然后间接执行该脚本文件,格式为./sed脚本文件 输入文件

其两种格局脚本文件须要以sha-bang(#!)标志开始。无论哪个种类艺术,假设没有点名输入文件,sed将从业内输入接收输入。常用选项有几个

选项 意义
-n 不打印所有的行到标准输出
-e 表示将下一个字符串解析为sed编辑命令,如果只传递一个,可以省略
-f 表示正在调用sed脚本文件

sed指令主要由定点文本行和sed编写命令两局地构成,有二种艺术固定文本:

  • 应用行号,指定一行,或许指定行号范围
  • 用正则表明式
选项 意义
x x为指定行号
x,y 指定从x到y的行号范围
/pattern/ 查询包含模式的行
/pattern/pattern/ 查询包含两个模式的行
/pattern/,x 从pattern匹配行到x号行
x,/pattern/ 上一条反过来
x,y! 查询不包括x和y行号的行

编排命令

选项 意义
p 打印匹配行
= 打印文件行号
a\ 在定位行号后追加文本信息
i\ 在定位行号之前插入文本信息
d 删除定位行
c\ 用新文本替代定位文本
s 使用替换模式替换相应模式
r 从另一个文件中读文本
w 将文本写入到一个文件
y 变换字符
q 第一个模式匹配后退出
l 显示与八进制ASCII码等价的控制字符
{} 在定位行执行的命令组
n 读取下一个输入行,用下一个命令处理新的行
h 将模式缓冲区的文本复制到保持缓冲区
H …追加到保持缓冲区
x 互换模式缓冲区和保持缓冲区内容
g 将保持模式缓冲区的内容复制到模式缓冲区
G ….追加到模式缓冲区

单引号

  • 和C语言同,Shell脚本中的单引号和双引号一样是字符串的界定符(双引号下一节介绍),而不是字符的界定符。单引号用于保证引号内所有字符的字面值,即便引号内的\和回车也不例外,可是字符串中不可以出现单引号。要是引号没有配对就输入回车,Shell会给出续行提醒符,须求用户把引号配上对。例如:

      $ echo '$SHELL'
      $SHELL
      $ echo 'ABC\(回车)
      > DE'(再按一次回车结束命令)
      ABC\
      DE
    

单引号

  • 和C语言同,Shell脚本中的单引号和双引号一样是字符串的界定符(双引号下一节介绍),而不是字符的界定符。单引号用于保险引号内存有字符的字面值,即便引号内的\和回车也不例外,可是字符串中无法冒出单引号。如果引号没有配对就输入回车,Shell会给出续行提醒符,必要用户把引号配上对。例如:

    $ echo '$SHELL'
    $SHELL
    $ echo 'ABC\(回车)
    > DE'(再按一次回车结束命令)
    ABC\
    DE
    

转义字符

  • 和C语言类似,\在Shell中被看做转义字符,用于去除紧跟其后的单个字符的非常意义(回车除外),换句话说,紧跟其后的字符取字面值。例如:

    $ echo $SHELL
    /bin/bash
    $ echo \$SHELL
    $SHELL
    $ echo \\
    \
    
  • 例如成立1个文书名为”$ $”的公文($间含有空格),可以如此:

    $ touch \$\ \$
    
  • 再有二个字符尽管不拥有卓殊意义,不过要用它做文件名也很勤奋,就是-号。假设要成立二个文本名以-号先河的文本,那样是不正确的:

    $ touch -hello
    touch:无效选项 -- e
    Try 'touch --help' for more information.
    
  • 就是加上\转义也依旧报错:

    $ touch \-hello
    touch:无效选项 -- e
    Try 'touch --help' for more information.
    
  • 因为各样UNIX命令都把-号开关的命令行参数作为命令的选项,而不会作为文件名。,即使非要处理以-号开头的文件名,只怕有三种办法:

    $ touch ./-hello
    或者
    $ touch -- -hello
    

示例

测试文件内容:

    This is a Certificate Request file:

    It should be mailed to zawu@seu.edu.cn

    =====================================================
    Certificate Subject:

    /O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus

    The above string is known as your user certificate subject, and t uniquely identifies theis user. $88
    To install this user certificate, please save this e-mail message into the following file.

    /home/alloy/linuxshell/CH02/usercert.pem

双引号

  • 被双引号用括住的内容,将被视为单一的字串。它幸免通配符增加,但允许变量扩张。那一点与单引号的处理格局分歧

      $ DATE=$(date)
      $ echo "$DATE"
      $ echo '$DATE'
    
  • 再比如:

      $ VAR=200
      $ echo $VAR
      200
      $ echo '$VAR'
      $VAR
      $ echo "$VAR"
      200
    

双引号

  • 被双引号用括住的始末,将被视为单一的字串。它避免通配符扩大,但允许变量扩张。那一点与单引号的处理形式不一致

    $ DATE=$(date)
    $ echo "$DATE"
    $ echo '$DATE'
    
  • 再比如:

    $ VAR=200
    $ echo $VAR
    200
    $ echo '$VAR'
    $VAR
    $ echo "$VAR"
    200
    

单引号

  • 和C语言同,Shell脚本中的单引号和双引号一样是字符串的界定符(双引号下一节介绍),而不是字符的界定符。单引号用于维持引号内拥有字符的字面值,即便引号内的\和回车也不例外,不过字符串中不或者出现单引号。即使引号没有配对就输入回车,Shell会给出续行指示符,需求用户把引号配上对。例如:

    $ echo '$SHELL'
    $SHELL
    $ echo 'ABC\(回车)
    > DE'(再按一次回车结束命令)
    ABC\
    DE
    

sed -n: 不打印sed编辑目的的整体内容

wsx@wsx-ubuntu:~/桌面$ sed -n '1p' input
    This is a Certificate Request file:

wsx@wsx-ubuntu:~/桌面$ sed '1p' input
    This is a Certificate Request file:
    This is a Certificate Request file:

    It should be mailed to zawu@seu.edu.cn

    =====================================================
    Certificate Subject:

    /O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus

    The above string is known as your user certificate subject, and t uniquely identifies theis user. $88
    To install this user certificate, please save this e-mail message into the following file.

    /home/alloy/linuxshell/CH02/usercert.pem

运用sed命令打印范围行:

wsx@wsx-ubuntu:~/桌面$ sed -n '3,6p' input 
    It should be mailed to zawu@seu.edu.cn

    =====================================================
    Certificate Subject:

Shell脚本语法

Shell脚本语法

双引号

  • 被双引号用括住的始末,将被视为单一的字串。它避免通配符伸张,但允许变量扩张。那点与单引号的处理方式不同

    $ DATE=$(date)
    $ echo "$DATE"
    $ echo '$DATE'
    
  • 再比如:

    $ VAR=200
    $ echo $VAR
    200
    $ echo '$VAR'
    $VAR
    $ echo "$VAR"
    200
    

sed -e: sed传递多少个编辑命令时行使

wsx@wsx-ubuntu:~/桌面$ sed -n '/Certificate/=' input 
1
6

wsx@wsx-ubuntu:~/桌面$ sed -n -e '/Certificate/p' input  -e '/Certificate/=' input
    This is a Certificate Request file:
1
    Certificate Subject:
6

标准测试

  • 命令test或[可以测试2个标准是还是不是建立,如若测试结果为真,则该命令的Exit
    Status为0,即使测试结果为假,则下令的Exit
    Status为1(注意与C语言的逻辑表示正好相反)。例如测试两个数的分寸关系:

      $ var=2
      $ test $var -gt 1
      $ echo $?
      0
      $ test $var -gt 3
      $ echo $?
      1
    
  • 尽管看起来很奇怪,但左侧括号[真的是一个发令的名字,传给命令的各参数之间应当用空格隔开,比如:$VA科雷傲、-gt、叁,]和[一声令下的八个参数,它们之间必须用空格隔开。命令test或[的参数格局是一致的,只可是test命令不必要]参数。以[一声令下为例,常见的测试命令如下表所示:

      [ -d DIR ]                 如果DIR存在并且是一个目录则为真
      [ -f FILE ]                如果FILE存在且是一个普通文件则为真
      [ -z STRING ]              如果STRING的长度为零则为真
      [ -n STRING ]              如果STRING的长度非零则为真
      [ STRING1 = STRING2 ]      如果两个字符串相同则为真
      [ STRING1 != STRING2 ]     如果两个字符串不相同则为真
      [ ARG1 OP ARG2 ]           ARG1和ARG2应该是整数或者取值为整数的变量,
                                 OP的值有:
                                      -eq     等于
                                      -ne     不等于
                                      -lt     小于
                                      -le     小于等于
                                      -gt     大于
                                      -ge     大于等于
    
  • 和C语言类似,测试条件之间仍可以做与、或、非逻辑运算:

      [ ! EXPR ]           EXPR可以是上表中的任意一种测试条件, !表示"逻辑反(非)"
      [EXPR1 -a EXPR2 ]    EXPR1和EXPR2可以是上表中的任意一种测试条件,-a表示“逻辑与”
      [EXPR1 -o EXPR2 ]    EXPR1和EXPR2可以是上表中的任意一种测试条件,-o表示“逻辑或”
    
  • 例如:

      $ VAR=abc
      $ [ -d Desktop -a $VAR = 'abc' ]
      $ echo $?
      0
    
  • 只顾,假若上例中的$VA智跑变量事先未曾概念,则被Shell展开为空字符串,会导致测试条件的语法错误(展开为[
    -d Desktop -a =
    ‘abc’]),用作一种好的Shell编程习惯,应该总是把变量取值放在双引号之中(展开为[
    -d Desktop -a “” = ‘abc’])

      $ unset VAR
      $ [ -d Desktop -a $VAR = 'abc' ]
      -bash: [: 参数太多
      $ [ -d Desktop -a "$VAR" = 'abc' ]
      $ echo $?
      1
    

标准化测试

  • 命令test或[可以测试几个规则是不是建立,如若测试结果为真,则该命令的Exit
    Status为0,如若测试结果为假,则下令的Exit
    Status为1(注意与C语言的逻辑表示正好相反)。例如测试八个数的轻重缓急关系:

    $ var=2
    $ test $var -gt 1
    $ echo $?
    0
    $ test $var -gt 3
    $ echo $?
    1
    
  • 虽说看起来很意外,但左手括号[当真是1个指令的名字,传给命令的各参数之间应该用空格隔开,比如:$VA帕杰罗、-gt、三,]和[一声令下的两个参数,它们中间必须用空格隔开。命令test或[的参数形式是千篇一律的,只可是test命令不须求]参数。以[一声令下为例,常见的测试命令如下表所示:

    [ -d DIR ]                 如果DIR存在并且是一个目录则为真
    [ -f FILE ]                如果FILE存在且是一个普通文件则为真
    [ -z STRING ]              如果STRING的长度为零则为真
    [ -n STRING ]              如果STRING的长度非零则为真
    [ STRING1 = STRING2 ]      如果两个字符串相同则为真
    [ STRING1 != STRING2 ]     如果两个字符串不相同则为真
    [ ARG1 OP ARG2 ]           ARG1和ARG2应该是整数或者取值为整数的变量,
                               OP的值有:
                                    -eq     等于
                                    -ne     不等于
                                    -lt     小于
                                    -le     小于等于
                                    -gt     大于
                                    -ge     大于等于
    
  • 和C语言类似,测试条件之间还足以做与、或、非逻辑运算:

    [ ! EXPR ]           EXPR可以是上表中的任意一种测试条件, !表示"逻辑反(非)"
    [EXPR1 -a EXPR2 ]    EXPR1和EXPR2可以是上表中的任意一种测试条件,-a表示“逻辑与”
    [EXPR1 -o EXPR2 ]    EXPR1和EXPR2可以是上表中的任意一种测试条件,-o表示“逻辑或”
    
  • 例如:

    $ VAR=abc
    $ [ -d Desktop -a $VAR = 'abc' ]
    $ echo $?
    0
    
  • 专注,如若上例中的$VA奥德赛变量事先未曾概念,则被Shell展开为空字符串,会导致测试条件的语法错误(展开为[
    -d Desktop -a =
    ‘abc’]),用作一种好的Shell编程习惯,应该总是把变量取值放在双引号之中(展开为[
    -d Desktop -a “” = ‘abc’])

    $ unset VAR
    $ [ -d Desktop -a $VAR = 'abc' ]
    -bash: [: 参数太多
    $ [ -d Desktop -a "$VAR" = 'abc' ]
    $ echo $?
    1
    

Shell脚本语法

sed -f:调用sed脚本文件时才起效用

wsx@wsx-ubuntu:~/桌面$ sed '/file:/a\We append a new line.' input 
    This is a Certificate Request file:
We append a new line.

    It should be mailed to zawu@seu.edu.cn

    =====================================================
    Certificate Subject:

    /O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus

    The above string is known as your user certificate subject, and t uniquely identifies theis user. $88
    To install this user certificate, please save this e-mail message into the following file.

    /home/alloy/linuxshell/CH02/usercert.pem

剧本用法:

#! /bin/sed -f 
/file:/a\       #a\表示在此处添加文本

# 添加文本
We append a new line.\
We append a another line.

sed基本编辑命令可以置身单引号内,也可放在单引号外。

分支

  • if/then/elif/else/fi

    • 和C语言类似,在Shell中用if、then、elif、else、fi这几条命令完结分支控制。那种流程控制语句本质上也是由若干条Shell命令组成的,例如在此以前讲过的

        if [ -f ~/.bashrc ]; then
            . ~/.bashrc
        fi
      
    • 骨子里是三条命令,if [ -f ~/.bashrc ]是第一条,then .
      ~/.bashrc是第二条,fi是第三条。倘若两条命令写在同一行则须求用;号隔开,一行只写一条命令就不要求写;号了,别的,then后边有换行,但那条命令没写完,Shell会自动续行,把下一行接在then后边当作一条命令处理。和[命令一样,要小心命令和各参数之间必须用空格隔开。if命令的参数组成一条子命令,若是该子命令的Exit
      Status为0(表示真),则实施then后边的子命令上,如果Exit
      Status非0(表示假),则执行elif、else大概fi前面的子命令。if后边的子命令平日是测试命令,但也可以是其他命令。Shell脚本没有{}括号,所以用fi表示if语句的收尾。见下例:

        #! /bin/sh
      
        if [ -f /bin/bash ]
        then
            echo "/bin/bash is a file"
        else
            echo "/bin/bash is NOT a file"
        fi
        if :; then echo "always true"; fi
      
    • “:”是3个异样的一声令下,称为空命令,该命令不做任何事,但Exit
      Status总是真。其它,也可以执行/bin/true或/bin/false拿到真或假的Exit
      Status。再看二个例子:

        #! /bin/sh
      
        echo "Is it morning? Please answer yes or no."
        read YES_OR_NO
        if [ "$YES_OR_NO" = "yes" ]; then
            echo "Good morning!"
        elif [ "$YES_OR_NO" = "no" ]; then
            echo "Good afternoon!"
        else
            echo "Sorry, $YES_OR_NO not recognized. Enter yes or no."
            exit 1
        fi
        exit 0
      
    • 上例中的read命令的成效是之类用户输入一行字符串,将该字符串存到1个Shell变量中。

    • 其它,Shell还提供了&&和||语法,和C语言类似,具有Short-circuit天性,很多Shell脚本喜欢写成这么:

        test "$(whoami)" != 'root' && (echo you are using a non-privileged account; exit 1)
      
    • &&约等于“if…then…”,而||相当于“if
      not…then…”。&&和||用于连接八个指令,而地方讲的-a和-o仅用于在测试表达式中老是三个测试条件,要专注它们的分别,例如:

        test "$VAR" -gt 1 -a "$VAR" -lt 3
      
    • 和以下写法是等价的

        test "$VAR" -gt 1 && test "$VAR" -lt 3
      
  • case/esac

    • case命令可类比C语言的switch/case语句,esac表示case语句块的甘休。C语言的case只可以合营整形或字符型常量表明式,而Shell脚本的case可以匹配字符串和Wildcard,每一个匹配分支可以有多少条命令,末尾必须以;;截至,执行时找到第二个很是的分段并实施相应的吩咐,然后径直跳到esac之后,不须要像C语言一样用break跳出。

        #! /bin/sh
      
        echo "Is it morning? Please answer yes or no."
        read YES_OR_NO
        case "$YES_OR_NO" in
        yes|y|Yes|YES)
            echo "Good Morning!";;
        [nN]*)
            echo "Good Afternoon!";;
        *)
            echo "Sorry, $YES_OR_NO not recognized. Enter yes or no."
            exit 1;;
        esac
        exit 0
      
    • 行使case语句的例证可以在系统服务的脚本目录/etc/init.d中找到。那几个目录下的本子大多具有那种方式(以/etc/init.d/nfs-kernel-server为例):

        case "$1" in 
            start)
                ...
            ;;
            stop)
                ...
            ;;
            status)
                ...
            ;;
            reload | force-reload)
                ...
            ;;
            restart)
                ...
            ;;
            *)
                log_sucess_msg "Usage: nfs-kernel-server {start|stop|status|reload|force-reload|restart}"
                exit 1
            ;;
        esac
      
    • 启航nfs-kernel-server服务的通令是

        $ sudo /etc/init.d/nfs-kernel-server start
      
    • $1是一个例外变量,在执行脚本时自动取值为率先个命令行参数,也等于start,所以进入start)分支执行有关的通令。同理,命令行参数指定为stop、reload或restart可以进来别的分支执行甘休服务、重新加载配置文件或重新开动服务的相干命令。

分支

  • if/then/elif/else/fi

    • 和C语言类似,在Shell中用if、then、elif、else、fi这几条命令完毕分支控制。那种流程控制语句本质上也是由若干条Shell命令组成的,例如之前讲过的

      if [ -f ~/.bashrc ]; then
          . ~/.bashrc
      fi
      
    • 其实是三条命令,if [ -f ~/.bashrc ]是第一条,then .
      ~/.bashrc是第二条,fi是第三条。若是两条命令写在同一行则要求用;号隔开,一行只写一条命令就不必要写;号了,其余,then前面有换行,但那条命令没写完,Shell会自动续行,把下一行接在then前面当作一条命令处理。和[指令一样,要小心命令和各参数之间必须用空格隔开。if命令的参数组成一条子命令,借使该子命令的Exit
      Status为0(表示真),则执行then前边的子命令上,如若Exit
      Status非0(表示假),则执行elif、else恐怕fi前面的子命令。if前面的子命令经常是测试命令,但也得以是其余命令。Shell脚本没有{}括号,所以用fi表示if语句的截至。见下例:

      #! /bin/sh
      
      if [ -f /bin/bash ]
      then
          echo "/bin/bash is a file"
      else
          echo "/bin/bash is NOT a file"
      fi
      if :; then echo "always true"; fi
      
    • “:”是3个特种的吩咐,称为空命令,该命令不做别的事,但Exit
      Status总是真。其余,也足以执行/bin/true或/bin/false拿到真或假的Exit
      Status。再看三个事例:

      #! /bin/sh
      
      echo "Is it morning? Please answer yes or no."
      read YES_OR_NO
      if [ "$YES_OR_NO" = "yes" ]; then
          echo "Good morning!"
      elif [ "$YES_OR_NO" = "no" ]; then
          echo "Good afternoon!"
      else
          echo "Sorry, $YES_OR_NO not recognized. Enter yes or no."
          exit 1
      fi
      exit 0
      
    • 上例中的read命令的功用是之类用户输入一行字符串,将该字符串存到二个Shell变量中。

    • 别的,Shell还提供了&&和||语法,和C语言类似,具有Short-circuit天性,很多Shell脚本喜欢写成那样:

      test "$(whoami)" != 'root' && (echo you are using a non-privileged account; exit 1)
      
    • &&相当于“if…then…”,而||相当于“if
      not…then…”。&&和||用于连接五个指令,而地方讲的-a和-o仅用于在测试表明式中再而三几个测试条件,要小心它们的差异,例如:

      test "$VAR" -gt 1 -a "$VAR" -lt 3
      
    • 和以下写法是等价的

      test "$VAR" -gt 1 && test "$VAR" -lt 3
      
  • case/esac

    • case命令可类比C语言的switch/case语句,esac表示case语句块的终结。C语言的case只可以协作整形或字符型常量表明式,而Shell脚本的case可以匹配字符串和魏尔德card,每种匹配分支可以有多少条命令,末尾必须以;;截止,执行时找到第二个门当户对的道岔并推行相应的命令,然后直接跳到esac之后,不需求像C语言一样用break跳出。

      #! /bin/sh
      
      echo "Is it morning? Please answer yes or no."
      read YES_OR_NO
      case "$YES_OR_NO" in
      yes|y|Yes|YES)
          echo "Good Morning!";;
      [nN]*)
          echo "Good Afternoon!";;
      *)
          echo "Sorry, $YES_OR_NO not recognized. Enter yes or no."
          exit 1;;
      esac
      exit 0
      
    • 动用case语句的例证可以在系统服务的本子目录/etc/init.d中找到。那一个目录下的剧本大多具有那种样式(以/etc/init.d/nfs-kernel-server为例):

      case "$1" in 
          start)
              ...
          ;;
          stop)
              ...
          ;;
          status)
              ...
          ;;
          reload | force-reload)
              ...
          ;;
          restart)
              ...
          ;;
          *)
              log_sucess_msg "Usage: nfs-kernel-server {start|stop|status|reload|force-reload|restart}"
              exit 1
          ;;
      esac
      
    • 运维nfs-kernel-server服务的一声令下是

      $ sudo /etc/init.d/nfs-kernel-server start
      
    • $1是2个新鲜变量,在推行脚本时自动取值为第3个命令行参数,相当于start,所以进入start)分支执行有关的一声令下。同理,命令行参数指定为stop、reload或restart可以进来其余分支执行截止服务、重新加载配置文件或重新启航服务的连锁命令。

基准测试

  • 命令test或[可以测试三个准绳是还是不是建立,假诺测试结果为真,则该命令的Exit
    Status为0,如若测试结果为假,则下令的Exit
    Status为1(注意与C语言的逻辑表示正好相反)。例如测试五个数的深浅关系:

    $ var=2
    $ test $var -gt 1
    $ echo $?
    0
    $ test $var -gt 3
    $ echo $?
    1
    
  • 虽说看起来很意外,但左边括号[真的是一个指令的名字,传给命令的各参数之间应当用空格隔开,比如:$VA途乐、-gt、3、]和[一声令下的多个参数,它们之间必须用空格隔开。命令test或[的参数方式是一模一样的,只然则test命令不必要]参数。以[一声令下为例,常见的测试命令如下表所示:

    [ -d DIR ]                 如果DIR存在并且是一个目录则为真
    [ -f FILE ]                如果FILE存在且是一个普通文件则为真
    [ -z STRING ]              如果STRING的长度为零则为真
    [ -n STRING ]              如果STRING的长度非零则为真
    [ STRING1 = STRING2 ]      如果两个字符串相同则为真
    [ STRING1 != STRING2 ]     如果两个字符串不相同则为真
    [ ARG1 OP ARG2 ]           ARG1和ARG2应该是整数或者取值为整数的变量,
                               OP的值有:
                                    -eq     等于
                                    -ne     不等于
                                    -lt     小于
                                    -le     小于等于
                                    -gt     大于
                                    -ge     大于等于
    
  • 和C语言类似,测试条件之间还足以做与、或、非逻辑运算:

    [ ! EXPR ]           EXPR可以是上表中的任意一种测试条件, !表示"逻辑反(非)"
    [EXPR1 -a EXPR2 ]    EXPR1和EXPR2可以是上表中的任意一种测试条件,-a表示“逻辑与”
    [EXPR1 -o EXPR2 ]    EXPR1和EXPR2可以是上表中的任意一种测试条件,-o表示“逻辑或”
    
  • 例如:

    $ VAR=abc
    $ [ -d Desktop -a $VAR = 'abc' ]
    $ echo $?
    0
    
  • 在意,假诺上例中的$VA兰德酷路泽变量事先未曾概念,则被Shell展开为空字符串,会导致测试条件的语法错误(展开为[
    -d Desktop -a =
    ‘abc’]),用作一种好的Shell编程习惯,应该总是把变量取值放在双引号之中(展开为[
    -d Desktop -a “” = ‘abc’])

    $ unset VAR
    $ [ -d Desktop -a $VAR = 'abc' ]
    -bash: [: 参数太多
    $ [ -d Desktop -a "$VAR" = 'abc' ]
    $ echo $?
    1
    

sed文本定位的一组例子

  1. 匹配元字符,用转义符\开展屏蔽

    wsx@wsx-ubuntu:~/桌面$ sed -n '/\./p' input 
     It should be mailed to zawu@seu.edu.cn
     /O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus
     The above string is known as your user certificate subject, and t uniquely identifies theis user. $88
     To install this user certificate, please save this e-mail message into the following file.
     /home/alloy/linuxshell/CH02/usercert.pem
    
  2. 采用元字符举行匹配

    $在sed命令中意味最后一行

    wsx@wsx-ubuntu:~/桌面$ sed -n '$p' input
     /home/alloy/linuxshell/CH02/usercert.pem
    
  3. !标志,打印不在2-10的行

    wsx@wsx-ubuntu:~/桌面$ sed -n '2,10!p' input 
     This is a Certificate Request file:
     To install this user certificate, please save this e-mail message into the following file.
    
     /home/alloy/linuxshell/CH02/usercert.pem
    
  4. 行使行号和第一字匹配限定行范围

    wsx@wsx-ubuntu:~/桌面$ sed -n '/seugrid/,$p' input 
     /O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus
    
     The above string is known as your user certificate subject, and t uniquely identifies theis user. $88
     To install this user certificate, please save this e-mail message into the following file.
    
     /home/alloy/linuxshell/CH02/usercert.pem
    

循环

  • for/do/done

    • Shell脚本的for循环结构和C语言很不雷同,它好像于某个编程语言foreach循环。例如:

        #! /bin/sh
      
        for FRUIT in apple banana pear; do
            echo "I like $FRUIT"
        done
      
    • FRUIT是二个循环变量,第一遍循环$FRUIT的取值是apple,第二次取值是banana,首次取值是pear。再比如说,要将当前目录下的chap0、chap一,chap2等文件夹名改为chap0~、chap1~、chap2~等(按惯例,末尾有~字符的公文名代表临时文件),这几个命令可以这么写:

        $ for FILENAME in chap?; do mv $FILENAME $FILENAME~; done
      
    • 也可以这样写:

        $ for FILENAME in `ls chap?`; do mv $FILENAME $FILENAME~; done
      
  • while/do/done

    • while的用法和C语言类似。比如八个验证码的台本:

        #! /bin/sh
      
        echo "Enter password:"
        read TRY
        while [ "$TRY" != "secret" ]; do
            echo "Sorry, try again"
            read TRY
        done
      
    • 下边的事例通过算术运算控制循环的次数:

        #! /bin/sh
      
        COUNTER=1
        while [ "$COUNTER" -lt 10 ]; do
            echo "Here we go again"
            COUNTER=$[$COUNTER+1]
        done
      
    • 另,Shell还有until循环,类似C语言的do…while。如有兴趣可在课后机动扩大学习。

  • break和continue

    • break[n]可以指定跳出几层循环;continue跳过这次巡回,但不会跳出循环。
    • 即break跳出,continue跳过。
    • 勤学苦练:将地方表达密码的主次修改一下,借使用户输错三回密码就报错退出。

循环

  • for/do/done

    • Shell脚本的for循环结构和C语言很不等同,它相仿于一些编程语言foreach循环。例如:

      #! /bin/sh
      
      for FRUIT in apple banana pear; do
          echo "I like $FRUIT"
      done
      
    • FRUIT是1个循环变量,第几次循环$FRUIT的取值是apple,第二次取值是banana,第三遍取值是pear。再譬如,要将当前目录下的chap0、chap一,chap2等公事夹名改为chap0~、chap1~、chap2~等(按惯例,末尾有~字符的文本名代表临时文件),这几个命令可以那样写:

      $ for FILENAME in chap?; do mv $FILENAME $FILENAME~; done
      
    • 也足以如此写:

      $ for FILENAME in `ls chap?`; do mv $FILENAME $FILENAME~; done
      
  • while/do/done

    • while的用法和C语言类似。比如二个验证码的剧本:

      #! /bin/sh
      
      echo "Enter password:"
      read TRY
      while [ "$TRY" != "secret" ]; do
          echo "Sorry, try again"
          read TRY
      done
      
    • 下边的例子通过算术运算控制循环的次数:

      #! /bin/sh
      
      COUNTER=1
      while [ "$COUNTER" -lt 10 ]; do
          echo "Here we go again"
          COUNTER=$[$COUNTER+1]
      done
      
    • 另,Shell还有until循环,类似C语言的do…while。如有兴趣可在课后自动扩大学习。

  • break和continue

    • break[n]可以指定跳出几层循环;continue跳过本次巡回,但不会跳出循环。
    • 即break跳出,continue跳过。
    • 勤学苦练:将方面表达密码的顺序修改一下,即便用户输错两回密码就报错退出。

分支

  • if/then/elif/else/fi

    • 和C语言类似,在Shell中用if、then、elif、else、fi这几条命令达成分支控制。那种流程控制语句本质上也是由若干条Shell命令组成的,例如在此之前讲过的

      if [ -f ~/.bashrc ]; then
          . ~/.bashrc
      fi
      
    • 实际是三条命令,if [ -f ~/.bashrc ]是率先条,then .
      ~/.bashrc是第二条,fi是第三条。要是两条命令写在同一行则须要用;号隔开,一行只写一条命令就不须要写;号了,此外,then后边有换行,但那条命令没写完,Shell会自动续行,把下一行接在then后边当作一条命令处理。和[命令一样,要留心命令和各参数之间必须用空格隔开。if命令的参数组成一条子命令,倘使该子命令的Exit
      Status为0(表示真),则执行then前面的子命令上,如若Exit
      Status非0(表示假),则执行elif、else或然fi后边的子命令。if后边的子命令常常是测试命令,但也得以是任何命令。Shell脚本没有{}括号,所以用fi表示if语句的扫尾。见下例:

      #! /bin/sh
      
      if [ -f /bin/bash ]
      then
          echo "/bin/bash is a file"
      else
          echo "/bin/bash is NOT a file"
      fi
      if :; then echo "always true"; fi
      
    • “:”是2个特有的命令,称为空命令,该命令不做其余事,但Exit
      Status总是真。其余,也得以执行/bin/true或/bin/false拿到真或假的Exit
      Status。再看3个例证:

      #! /bin/sh
      
      echo "Is it morning? Please answer yes or no."
      read YES_OR_NO
      if [ "$YES_OR_NO" = "yes" ]; then
          echo "Good morning!"
      elif [ "$YES_OR_NO" = "no" ]; then
          echo "Good afternoon!"
      else
          echo "Sorry, $YES_OR_NO not recognized. Enter yes or no."
          exit 1
      fi
      exit 0
      
    • 上例中的read命令的效率是之类用户输入一行字符串,将该字符串存到一个Shell变量中。

    • 其它,Shell还提供了&&和||语法,和C语言类似,具有Short-circuit本性,很多Shell脚本喜欢写成这么:

      test "$(whoami)" != 'root' && (echo you are using a non-privileged account; exit 1)
      
    • &&约等于“if…then…”,而||约等于“if
      not…then…”。&&和||用于连接多少个指令,而位置讲的-a和-o仅用于在测试表明式中连连七个测试条件,要注意它们的不一致,例如:

      test "$VAR" -gt 1 -a "$VAR" -lt 3
      
    • 和以下写法是等价的

      test "$VAR" -gt 1 && test "$VAR" -lt 3
      
  • case/esac

    • case命令可类比C语言的switch/case语句,esac代表case语句块的了断。C语言的case只可以协作整形或字符型常量表明式,而Shell脚本的case可以匹配字符串和魏尔德card,各个匹配分支可以有若干条命令,末尾必须以;;截止,执行时找到第2个门当户对的分段并推行相应的一声令下,然后直接跳到esac之后,不需求像C语言一样用break跳出。

      #! /bin/sh
      
      echo "Is it morning? Please answer yes or no."
      read YES_OR_NO
      case "$YES_OR_NO" in
      yes|y|Yes|YES)
          echo "Good Morning!";;
      [nN]*)
          echo "Good Afternoon!";;
      *)
          echo "Sorry, $YES_OR_NO not recognized. Enter yes or no."
          exit 1;;
      esac
      exit 0
      
    • 运用case语句的例证可以在系统服务的台本目录/etc/init.d中找到。那几个目录下的脚本大多具有那种情势(以/etc/init.d/nfs-kernel-server为例):

      case "$1" in 
          start)
              ...
          ;;
          stop)
              ...
          ;;
          status)
              ...
          ;;
          reload | force-reload)
              ...
          ;;
          restart)
              ...
          ;;
          *)
              log_sucess_msg "Usage: nfs-kernel-server {start|stop|status|reload|force-reload|restart}"
              exit 1
          ;;
      esac
      
    • 起步nfs-kernel-server服务的吩咐是

      $ sudo /etc/init.d/nfs-kernel-server start
      
    • $1是贰个特殊变量,在推行脚本时自动取值为率先个命令行参数,约等于start,所以进入start)分支执行有关的授命。同理,命令行参数指定为stop、reload或restart可以进去其它分支执行为止服务、重新加载配置文件或再度开动服务的相干命令。

sed基本编辑命令的一组例子

  1. 插入文本:运行脚本,以输入文件名作为参数

    #!/bin/sed -f
    /file:/i\             # i\表示此处换行插入文本
    We insert a new line.
    
  2. 修改文件

    #!/bin/sed -f
    
    /file:/c\             #c\表示此处换行修改文本
    We modify this line      #修改文本内容
    
  3. 去除文本,符号是d,不带\,与任何命令有所不相同,至极灵活。上面删除第一行和最后一行。

    wsx@wsx-ubuntu:~/桌面$ sed '1d' input
    
     It should be mailed to zawu@seu.edu.cn
    
     =====================================================
     Certificate Subject:
    
     /O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus
    
     The above string is known as your user certificate subject, and t uniquely identifies theis user. $88
     To install this user certificate, please save this e-mail message into the following file.
    
     /home/alloy/linuxshell/CH02/usercert.pem
    wsx@wsx-ubuntu:~/桌面$ sed '$d' input
     This is a Certificate Request file:
    
     It should be mailed to zawu@seu.edu.cn
    
     =====================================================
     Certificate Subject:
    
     /O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus
    
     The above string is known as your user certificate subject, and t uniquely identifies theis user. $88
     To install this user certificate, please save this e-mail message into the following file.
    
  4. 轮换文本,格式s/被替换的字符串/新字符串/[替换选项]

    选项 意义
    g 全局匹配替换(替换所有的)
    p 与-n选项结合,只打印替换行
    w 文件名 表示将输出定向到一个文件
    sx@wsx-ubuntu:~/桌面$ sed 's/Certificate/CERTIFICATE/' input
     This is a CERTIFICATE Request file:
    
     It should be mailed to zawu@seu.edu.cn
    
     =====================================================
     CERTIFICATE Subject:
    
     /O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus
    
     The above string is known as your user certificate subject, and t uniquely identifies theis user. $88
     To install this user certificate, please save this e-mail message into the following file.
    
     /home/alloy/linuxshell/CH02/usercert.pem
    wsx@wsx-ubuntu:~/桌面$ sed -n 's/Certificate/CERTIFICATE/p' input
     This is a CERTIFICATE Request file:
     CERTIFICATE Subject:
    
  5. 写入到三个新文件

    wsx@wsx-ubuntu:~/桌面$ sed -n 's/Certificate/CERTIFICATE/pg' input
     This is a CERTIFICATE Request file:
     CERTIFICATE Subject:
    wsx@wsx-ubuntu:~/桌面$ 
    wsx@wsx-ubuntu:~/桌面$ sed -n '1,5 w output' input
    wsx@wsx-ubuntu:~/桌面$ cat output 
     This is a Certificate Request file:
    
     It should be mailed to zawu@seu.edu.cn
    
     =====================================================
    
  6. 从文件中可读入文本,格式指定地址 r 文件名

  7. 退出命令:q

  8. 转移命令:sed命令的y意味着字符变换(不等长时会报错)

    wsx@wsx-ubuntu:~/桌面$ sed 'y/fmj/FMJ/' input 
     This is a CertiFicate Request File:
    
     It should be Mailed to zawu@seu.edu.cn
    
     =====================================================
     CertiFicate SubJect:
    
     /O=Grid/OU=GlobusTest/OU=siMpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus
    
     The above string is known as your user certiFicate subJect, and t uniquely identiFies theis user. $88
     To install this user certiFicate, please save this e-Mail Message into the Following File.
    
     /hoMe/alloy/linuxshell/CH02/usercert.peM
    
  9. 来得控制字符:控制字符就是非打印字符,如退格键、F1键等。使用sed l命令。

  10. 在命令行执行命令组,用{}符号,与-e分选成效相近。

    wsx@wsx-ubuntu:~/桌面$ sed -n '/Certificate/{p;=}' input
        This is a Certificate Request file:
    1
        Certificate Subject:
    6
    

任务参数和至极变量

  • 有无数新鲜变量是被Shell自动赋值的,大家早就蒙受了$?和$1。其余常用的职位参数和特殊变量在此地总计一下:

      $0           相当于C语言main函数的argv[0]
      $1、$2...    这些称为位置参数(Positional Parameter),相当于C语言main函数的argv[1]、argv[2]...
      $#           相当于C语言main函数的argc - 1,注意这里的#后面不表示注释
      $@           表示参数"$1" "$2" ...,例如可以用在for循环中的in后面 
      $*           表示参数"$1" "$2" ...,同上
      $?           上一条命令的Exit Status
      $$           当前进程号
    
  • 地点参数可以用shift命令左移。比如shift
    3表示原本的$4以往改成$1,原来的$5将来改成$2等等,原来的$1、$2、$3废弃,$0不移动。不带参数的shift命令相当于shift
    1。例如:

      #! /bin/sh
    
      echo "The program $0 is now running"
      echo "The first parameter is $1"
      echo "The second parameter is $2"
      echo "The parameter list is $@"
      shift
      echo "The first parameter is $1"
      echo "The second parameter is $2"
      echo "The parameter list is $@"
    

职位参数和特殊变量

  • 有诸多奇特变量是被Shell自动赋值的,大家已经遭逢了$?和$1。其余常用的岗位参数和特种变量在此处统计一下:

    $0           相当于C语言main函数的argv[0]
    $1、$2...    这些称为位置参数(Positional Parameter),相当于C语言main函数的argv[1]、argv[2]...
    $#           相当于C语言main函数的argc - 1,注意这里的#后面不表示注释
    $@           表示参数"$1" "$2" ...,例如可以用在for循环中的in后面 
    $*           表示参数"$1" "$2" ...,同上
    $?           上一条命令的Exit Status
    $$           当前进程号
    
  • 义务参数能够用shift命令左移。比如shift
    3表示原本的$4今后成为$1,原来的$5未来变成$2等等,原来的$一,$2、$3甩掉,$0不活动。不带参数的shift命令也就是shift
    1。例如:

    #! /bin/sh
    
    echo "The program $0 is now running"
    echo "The first parameter is $1"
    echo "The second parameter is $2"
    echo "The parameter list is $@"
    shift
    echo "The first parameter is $1"
    echo "The second parameter is $2"
    echo "The parameter list is $@"
    

循环

  • for/do/done

    • Shell脚本的for循环结构和C语言很不同,它好像于有个别编程语言foreach循环。例如:

      #! /bin/sh
      
      for FRUIT in apple banana pear; do
          echo "I like $FRUIT"
      done
      
    • FRUIT是三个循环变量,第两遍循环$FRUIT的取值是apple,第二次取值是banana,第三遍取值是pear。再比如,要将当前目录下的chap0、chap壹,chap2等文件夹名改为chap0~、chap1~、chap2~等(按惯例,末尾有~字符的文本名代表临时文件),那个命令可以如此写:

      $ for FILENAME in chap?; do mv $FILENAME $FILENAME~; done
      
    • 也得以这么写:

      $ for FILENAME in `ls chap?`; do mv $FILENAME $FILENAME~; done
      
  • while/do/done

    • while的用法和C语言类似。比如多少个验证码的剧本:

      #! /bin/sh
      
      echo "Enter password:"
      read TRY
      while [ "$TRY" != "secret" ]; do
          echo "Sorry, try again"
          read TRY
      done
      
    • 上边的事例通过算术运算控制循环的次数:

      #! /bin/sh
      
      COUNTER=1
      while [ "$COUNTER" -lt 10 ]; do
          echo "Here we go again"
          COUNTER=$[$COUNTER+1]
      done
      
    • 另,Shell还有until循环,类似C语言的do…while。如有兴趣可在课后自动扩大学习。

  • break和continue

    • break[n]可以指定跳出几层循环;continue跳过本次巡回,但不会跳出循环。
    • 即break跳出,continue跳过。
    • 勤学苦练:将地点表达密码的次序修改一下,如若用户输错一遍密码就报错退出。

awk编程

awk是2位长辈开发的编程语言,awk是三个人创小编的首字母。基本语言与C类似。

当前,使用的是gawk,Linux系统中/bin目录下有awkgawk八个指令,前者实际上是后者的链接。利用gawk言语可以兑现数量检索、抽取文件中的数据、成立管道流命令等效果。

大家得以归纳地将awk编程模型分位两个等级:

  • 读输入文件进行的举办代码段(由BEGIN关键字标识)
  • 读取输入文件时实施代码段
  • 读输入文件从此的实施代码段(由END关键字标识)

调用方法分为两种:Sehll命令行形式;脚本执行。

输入输出

  • echo

    • 显示文本行或变量,可能把字符串输入到文件。

        echo [option] string
        -e 解析转义字符
        -n 不回车换行。默认情况echo回显的内容后面跟一个回车换行。
        echo "hello\n\n"
        echo -e "hello\n\n"
        echo "hello"
        echo -n "hello"
      
  • 管道

    • 可以透过 | 把三个发令的出口传递给另二个限令做输入。

        cat myfile | more
        ls -l | grep "myfile"
        df -k | awk '{print $1}' | grep -v "文件系统"
        df -k 查看磁盘空间,找到第一列,去除“文件系统”,并输出
      
  • tee

    • tee命令把结果输出到专业输出,另3个副本输出到对应文件。

        df -k | awk '{print $1}' | grep -v "文件系统" | tee a.txt
      
    • tee -a a.txt表示追加操作。

        df -k | awk '{print $1}' | grep -v "文件系统" | tee -a a.txt        
      
  • 文本重定向

      cmd > file              把标准输出重定向到新文件中
      cmd >> file             追加
      cmd > file2 2>&1        标准出错也重定向到1所指向的file里
      cmd >> file2 2>&1       
      cmd < file1 > file2     输入输出都定向到文件里
      cmd < &fd               把文件描述符fd作为标准输入
      cmd > &fd               把文件描述符fd作为标准输出
      cmd < &-                关闭标准输入
    

输入输出

  • echo

    • 体现文本行或变量,恐怕把字符串输入到文件。

      echo [option] string
      -e 解析转义字符
      -n 不回车换行。默认情况echo回显的内容后面跟一个回车换行。
      echo "hello\n\n"
      echo -e "hello\n\n"
      echo "hello"
      echo -n "hello"
      
  • 管道

    • 可以透过 | 把二个限令的输出传递给另三个下令做输入。

      cat myfile | more
      ls -l | grep "myfile"
      df -k | awk '{print $1}' | grep -v "文件系统"
      df -k 查看磁盘空间,找到第一列,去除“文件系统”,并输出
      
  • tee

    • tee命令把结果输出到标准输出,另3个副本输出到对应文件。

      df -k | awk '{print $1}' | grep -v "文件系统" | tee a.txt
      
    • tee -a a.txt表示追加操作。

      df -k | awk '{print $1}' | grep -v "文件系统" | tee -a a.txt        
      
  • 文本重定向

    cmd > file              把标准输出重定向到新文件中
    cmd >> file             追加
    cmd > file2 2>&1        标准出错也重定向到1所指向的file里
    cmd >> file2 2>&1       
    cmd < file1 > file2     输入输出都定向到文件里
    cmd < &fd               把文件描述符fd作为标准输入
    cmd > &fd               把文件描述符fd作为标准输出
    cmd < &-                关闭标准输入
    

职位参数和独特变量

  • 有不计其数与众不一样变量是被Shell自动赋值的,大家已经蒙受了$?和$1。其余常用的地点参数和特有变量在那里总计一下:

    $0           相当于C语言main函数的argv[0]
    $1、$2...    这些称为位置参数(Positional Parameter),相当于C语言main函数的argv[1]、argv[2]...
    $#           相当于C语言main函数的argc - 1,注意这里的#后面不表示注释
    [email protected]           表示参数"$1" "$2" ...,例如可以用在for循环中的in后面 
    $*           表示参数"$1" "$2" ...,同上
    $?           上一条命令的Exit Status
    $$           当前进程号
    
  • 任务参数可以用shift命令左移。比如shift
    3表示原本的$4以后变成$1,原来的$5以往变为$2等等,原来的$壹,$二,$3放弃,$0不挪窝。不带参数的shift命令相当于shift
    1。例如:

    #! /bin/sh
    
    echo "The program $0 is now running"
    echo "The first parameter is $1"
    echo "The second parameter is $2"
    echo "The parameter list is [email protected]"
    shift
    echo "The first parameter is $1"
    echo "The second parameter is $2"
    echo "The parameter list is [email protected]"
    

awk格局匹配

任何awk语句都由格局和动作结合。方式是一组用于测试输入行是否须求执行动作的条条框框,动作是包蕴语句、函数和表明式的施行进度。awk支撑所有的正则表明式元字符,以及?+八个扩展元字符。

wsx@wsx-ubuntu:~/桌面$ awk '/^$/{print "This is a blank line."}' input
This is a blank line.
This is a blank line.
This is a blank line.
This is a blank line.
This is a blank line.

单引号中间为awk命令,由两某个构成,以“/”符号分隔,^$是方式,花括号部分是动作。该awk表示若是读入的输入文件是空行,就打印后边的字符串This is a blank line

运用脚本(将下令输入三个文本中):

wsx@wsx-ubuntu:~/桌面$ awk -f src.awk input
This is a blank line.
This is a blank line.
This is a blank line.
This is a blank line.
This is a blank line.

故事情节不止这一个,我们先谈谈其余概念。

函数

  • 和C语言类似,Shell中也有函数的概念,可是函数定义中从不重返值也未曾子数列表。例如:

      #/bin/sh
    
      foo(){ echo "Function foo is called"; }
    
      echo "-=start=-"
      foo
      echo "-=end=-"
    
  • 小心函数体的左花括号{和前边的下令之间必须有空格或换行,借使将最终一条命令和右花括号}写在一行,命令末尾必须有分公司;但,不指出将函数定义的写在一行上,不便利脚本阅读。

  • 在定义foo()函数时并不执行函数体中的命令,就象定义变量一样,只是给foo那么些名3个定义,到后边调用foo函数的时候(注意Shell中的函数调用不写括号)才执行函数体中的命令。Shell脚本中的函数必须先定义后调用,一般把函数定义语句写在剧本的前边,把函数调用和其他命令写在本子的最后(类似C语言中的main函数,那才是整个脚本实际开端执行命令的地点)。
  • Shell函数没有参数列表并不代表无法传参数,事实上,函数就象是迷你脚本,调用函数时方可传任意个参数,在函数内部同样是用$0、$一,$2等变量来领取参数,函数中的地方参数也等于函数的有个别变量,改变那些变量并不会影响外面的$0、$壹,$2等变量。函数中得以用return命令归来,假设return前面跟一个数字则代表函数的Exit
    Status。
  • 上边这么些剧本可以一遍创制多个目录,各目录名经过命令行参数传入,脚本逐个测试各目录是或不是留存,若是目录不设有,首先打印消息然后试着创造该目录。

      #! /bin/sh
      is_directory(){
          DIR_ANME=$1
          if [ ! -d $DIR_ANME ]
              return 1
          else
              return 0
          fi
      }
    
      for DIR in "$@"; do
          if is_directory "$DIR"
          then : 
          else
              echo "$DIR doesn't exist, Creating it now..."
              mkdir $DIR > /dev/null 2>&1
              if [ $? -ne 0 ]; then
                  echo "Cannot create directory $DIR"
                  exit 1
              fi
          fi
      done
    
  • 注意:is_directory返回0表示真,返回1表示假

函数

  • 和C语言类似,Shell中也有函数的概念,然而函数定义中绝非重回值也不曾子数列表。例如:

    #/bin/sh
    
    foo(){ echo "Function foo is called"; }
    
    echo "-=start=-"
    foo
    echo "-=end=-"
    
  • 在意函数体的左花括号{和前边的吩咐之间必须有空格或换行,如果将最终一条命令和右花括号}写在一行,命令末尾必须有分公司;但,不提出将函数定义的写在一行上,不便于脚本阅读。

  • 在定义foo()函数时并不执行函数体中的命令,就象定义变量一样,只是给foo那一个名3个概念,到背后调用foo函数的时候(注意Shell中的函数调用不写括号)才执行函数体中的命令。Shell脚本中的函数必须先定义后调用,一般把函数定义语句写在本子的前头,把函数调用和其它命令写在剧本的最终(类似C语言中的main函数,那才是所有脚本实际起初执行命令的地点)。
  • Shell函数没有参数列表并不表示无法传参数,事实上,函数就象是迷你脚本,调用函数时得以传任意个参数,在函数内部同样是用$0、$一,$2等变量来领取参数,函数中的地点参数约等于函数的有个别变量,改变这一个变量并不会影响外面的$0、$一,$2等变量。函数中可以用return命令归来,假如return前边跟三个数字则意味着函数的Exit
    Status。
  • 上边那么些剧本可以三回创设两个目录,各目录名经过命令行参数传入,脚本每个测试各目录是还是不是留存,假设目录不设有,首先打印消息然后试着创制该目录。

    #! /bin/sh
    is_directory(){
        DIR_ANME=$1
        if [ ! -d $DIR_ANME ]
            return 1
        else
            return 0
        fi
    }
    
    for DIR in "$@"; do
        if is_directory "$DIR"
        then : 
        else
            echo "$DIR doesn't exist, Creating it now..."
            mkdir $DIR > /dev/null 2>&1
            if [ $? -ne 0 ]; then
                echo "Cannot create directory $DIR"
                exit 1
            fi
        fi
    done
    
  • 注意:is_directory返回0表示真,返回1表示假

输入输出

  • echo

    • 突显文本行或变量,恐怕把字符串输入到文件。

      echo [option] string
      -e 解析转义字符
      -n 不回车换行。默认情况echo回显的内容后面跟一个回车换行。
      echo "hello\n\n"
      echo -e "hello\n\n"
      echo "hello"
      echo -n "hello"
      
  • 管道

    • 可以透过 | 把三个命令的输出传递给另一个指令做输入。

      cat myfile | more
      ls -l | grep "myfile"
      df -k | awk '{print $1}' | grep -v "文件系统"
      df -k 查看磁盘空间,找到第一列,去除“文件系统”,并输出
      
  • tee

    • tee命令把结果输出到标准输出,另1个副本输出到对应文件。

      df -k | awk '{print $1}' | grep -v "文件系统" | tee a.txt
      
    • tee -a a.txt表示追加操作。

      df -k | awk '{print $1}' | grep -v "文件系统" | tee -a a.txt        
      
  • 文件重定向

    cmd > file              把标准输出重定向到新文件中
    cmd >> file             追加
    cmd > file2 2>&1        标准出错也重定向到1所指向的file里
    cmd >> file2 2>&1       
    cmd < file1 > file2     输入输出都定向到文件里
    cmd < &fd               把文件描述符fd作为标准输入
    cmd > &fd               把文件描述符fd作为标准输出
    cmd < &-                关闭标准输入
    

笔录和域

awk认为输入文件是结构化的,awk将每一种输入文件行定义为记录,行中的每3个字符串定义为域,域之间用空格、TAB键或任何标志举行分隔,分隔域的标记就叫分隔符。(这一个结构化概念须要领会,很多下令和编程中都有关联)

wsx@wsx-ubuntu:~/桌面$ awk '{print $2,$1,$4,$3}' sturecord 
Hao Li 025------------ njue
Ju Zhang 025---------- nju
Bin Wang 025------ seu
wsx@wsx-ubuntu:~/桌面$ awk '{print $0}' sturecord 
Li Hao  njue 025------------ 
Zhang Ju    nju 025---------- 
Wang Bin    seu 025------

可以经过对域的操作对文件举办重新排列,也可以用print $0输入所有域。

wsx@wsx-ubuntu:~/桌面$ awk 'BEGIN {one=1;two=2}{print $(one+two)}' sturecord 
njue
nju
seu

BEGIN字段中定义onetwo八个变量并赋值。

-F选拔用来改变分隔符,例如只以’\t’为分隔符。

wsx@wsx-ubuntu:~/桌面$ awk -F'\t' '{print $2}' sturecord 
025------------ 
025---------- 
025------

注意-F-f的区别。

awk还提供了另一种更有益的措施改变分隔符。

wsx@wsx-ubuntu:~/桌面$ cat sturecord 
Li Hao,njue,025------------ 
Zhang Ju,nju,025---------- 
Wang Bin,seu,025------
wsx@wsx-ubuntu:~/桌面$ awk 'BEGIN {FS=","}{print $1, $3}' sturecord 
Li Hao 025------------ 
Zhang Ju 025---------- 
Wang Bin 025------

Shell脚本调试方法

  • Shell提供了有些用来调试脚本的选项,如:

      -n      读一遍脚本中的命令但不执行,用于检查脚本中的语法错误。
      -v      一边执行脚本, 一边将执行过的脚本命令打印到标准错误输出。
      -x      提供跟踪执行信息,将执行的每一条命令和结果依次打印出来。
    
  • 那么些选拔有二种常见的应用格局:

  • 1、在命令行提供参数。如:

      $ sh -x ./script.sh
    
  • 贰,在剧本开关提供参数。如:

      #! /bin/sh -x
    
  • 三,在剧本中用set命令运行或剥夺参数。如:

      #! /bin/sh
    
      if [ -z "$1" ]; then
          set -x
          echo "ERROR: Insufficient Args."
          exit 1
          set +x
      fi
    
  • set -x和set
    +x分别代表启用或剥夺-x参数,那样可以只对剧本中的某一段展开跟踪调试。

Shell脚本调试方法

  • Shell提供了有的用来调试脚本的选项,如:

    -n      读一遍脚本中的命令但不执行,用于检查脚本中的语法错误。
    -v      一边执行脚本, 一边将执行过的脚本命令打印到标准错误输出。
    -x      提供跟踪执行信息,将执行的每一条命令和结果依次打印出来。
    
  • 这么些采用有二种普遍的行使办法:

  • 一,在命令行提供参数。如:

    $ sh -x ./script.sh
    
  • 二,在剧本开关提供参数。如:

    #! /bin/sh -x
    
  • 三,在本子中用set命令运维或剥夺参数。如:

    #! /bin/sh
    
    if [ -z "$1" ]; then
        set -x
        echo "ERROR: Insufficient Args."
        exit 1
        set +x
    fi
    
  • set -x和set
    +x分别表示启用或剥夺-x参数,那样可以只对台本中的某一段举行跟踪调试。

函数

  • 和C语言类似,Shell中也有函数的概念,可是函数定义中从不再次来到值也不曾子舆数列表。例如:

    #/bin/sh
    
    foo(){ echo "Function foo is called"; }
    
    echo "-=start=-"
    foo
    echo "-=end=-"
    
  • 注意函数体的左花括号{和后边的命令之间必须有空格或换行,尽管将最终一条命令和右花括号}写在一行,命令末尾必须有分公司;但,不指出将函数定义的写在一行上,不便于脚本阅读。

  • 在定义foo()函数时并不执行函数体中的命令,就象定义变量一样,只是给foo这个名1个定义,到背后调用foo函数的时候(注意Shell中的函数调用不写括号)才执行函数体中的命令。Shell脚本中的函数必须先定义后调用,一般把函数定义语句写在本子的前头,把函数调用和别的命令写在剧本的最后(类似C语言中的main函数,那才是整套脚本实际初步执行命令的地点)。

  • Shell函数没有参数列表并不代表无法传参数,事实上,函数就象是迷你脚本,调用函数时得以传任意个参数,在函数内部同样是用$0、$一,$2等变量来领取参数,函数中的地方参数也等于函数的有个别变量,改变这个变量并不会影响外面的$0、$1、$2等变量。函数中得以用return命令归来,倘使return前面跟3个数字则代表函数的Exit
    Status。
  • 上面这个剧本可以一次创设多少个目录,各目录名经过命令行参数传入,脚本每种测试各目录是不是存在,即使目录不设有,首先打印音讯然后试着创建该目录。

    #! /bin/sh
    is_directory(){
        DIR_ANME=$1
        if [ ! -d $DIR_ANME ]
            return 1
        else
            return 0
        fi
    }
    
    for DIR in "[email protected]"; do
        if is_directory "$DIR"
        then : 
        else
            echo "$DIR doesn't exist, Creating it now..."
            mkdir $DIR > /dev/null 2>&1
            if [ $? -ne 0 ]; then
                echo "Cannot create directory $DIR"
                exit 1
            fi
        fi
    done
    
  • 注意:is_directory返回0表示真,返回1表示假

涉及和布尔运算符

awk定义了一组关系运算符用于awk格局匹配。如下表

运算符 意义
< 小于
> 大于
<= 小于或等于
>= 大于或等于
== 等于
!= 不等于
~ 匹配正则表达式
!~ 不匹配正则表达式

用/etc/passwd文件做个例证

# 第1域匹配root
wsx@wsx-ubuntu:~/桌面$ awk 'BEGIN {FS=":"} $1~/root/' /etc/passwd
# 全部域匹配root
root:x:0:0:root:/root:/bin/bash
wsx@wsx-ubuntu:~/桌面$ awk 'BEGIN {FS=":"} $0~/root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
# 全部域不匹配nologin
wsx@wsx-ubuntu:~/桌面$ awk 'BEGIN {FS=":"} $0!~/nologin/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
sync:x:4:65534:sync:/bin:/bin/sync
systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
syslog:x:104:108::/home/syslog:/bin/false
_apt:x:105:65534::/nonexistent:/bin/false
messagebus:x:106:110::/var/run/dbus:/bin/false
uuidd:x:107:111::/run/uuidd:/bin/false
lightdm:x:108:114:Light Display Manager:/var/lib/lightdm:/bin

awk条件语句与C类似,有if语句,if/else语句以及if/else else语句三种。

上面是支撑的布尔运算符

运算符 意义
|| 逻辑或
&& 逻辑与
! 逻辑非
# 多条件精确匹配
wsx@wsx-ubuntu:~/桌面$ awk 'BEGIN {FS=":"} {if($3==10||$4==10) print $0}' /etc/passwd
# 多条件模糊匹配
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
wsx@wsx-ubuntu:~/桌面$ awk 'BEGIN {FS=":"} {if($3~10||$4~10) print $0}' /etc/passwd
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
syslog:x:104:108::/home/syslog:/bin/false
_apt:x:105:65534::/nonexistent:/bin/false
messagebus:x:106:110::/var/run/dbus:/bin/false
uuidd:x:107:111::/run/uuidd:/bin/false
lightdm:x:108:114:Light Display Manager:/var/lib/lightdm:/bin/false
whoopsie:x:109:116::/nonexistent:/bin/false
avahi-autoipd:x:110:119:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/bin/false
wsx:x:1000:1000:wsx,,,:/home/wsx:/bin/bash
nx:x:123:1001::/var/NX/nx:/etc/NX/nxserver

正则表明式

  • 先前小编们用grep在二个文件中找出含有有些字符串的行,比如在头文件中找出2个宏定义。其实grep还可以够找出符合有个别格局(Pattern)的一类字符串。例如找出具有符合xxx@xxx.xxx方式的字符串(约等于email地址),需求x字符可以是字母、数字、下划线、小数点或减号,email地址的每一局地可以有一个或七个x字符,例如abc.d@ef.com、1_2@987-6.54,当然吻合那些格局的不全是合法的email地址,但起码可以做五遍始发筛选,筛掉a.b、c@d等一定不是email地址的字符串。再譬如,找出富有符合yyy-yyy-yyy-yyy方式的字符串(约等于IP地址),须要y是0-9的数字,IP地址的每一部分可以有1-三个y字符。
  • 一经用grep查找多少个方式,怎样表示那么些模式,这一类字符串,而不是一定的字符串呢?从那八个大致的例证可以看出,要代表二个情势至少应该包蕴以下音讯:
  • 字符类(Character
    Class):如上例的x和y,它们在械中意味三个字符,不过取值范围是一类字符中的任意3个。
  • 数量限定符(Quantifier):邮件地址的各种有些可以有2个或八个x字符,IP地址的每一局地可以有1-一个y字符。
  • 各类字符类以及常见字符之间的地点关系:例如邮件地址分三部分,用一般字符@和.隔开,IP地址分四有个别,用.隔开,每一有的都足以字符类和多少限制符描述。为了表示地方关系,还有地方限定符(Anchor)的定义,将在底下介绍。
  • 确定部分尤其语法表示字符类、数量限定符和职位关系,然后用那些杰出语法和平凡字符一起表示三个方式,那就是正则表明式(Regular
    Expression)。例如email地址的正则表明式可以写成[a-zA-Z0-9.-]+@[a-zA-Z0-9.-]+.[a-zA-Z0-9_.-]+,IP地址的正则表达式可以写成[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}。下一节介绍正则表明式的语法,我们先看看正则表达式在grep中怎么用。例如有如此一个文书testfile:

      192.168.1.1
      1234.234.04.5678
      123.4234.045.678
      abcde
    
      $ egrep '[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}' testfile
      192.168.1.1
      1234.234.04.5678
    
  • egrep相当于grep
    -E,表示接纳Extended正则表明式语法。grep的正则表明式有Basic和Extended二种标准,它们中间的分别下一节再解释。别的还有fgrep命令,也等于grep
    -F,表示只搜索一定字符而不搜索正则表达式方式,不会按正则表明式的语法解释前面的参数。

  • 专注正则表明式参数用单引号括起来了,因为正则表明式中用到的居多特殊字符在Shell中也有例外意义(例如),只有用单引号括起来才能确保那些字符稳如武当山地传给grep命令,而不会被Shell解释掉。
  • 192.168.1.1相符上述情势,由多少个.隔开的四段组成,每段都以1到二个数字,所以这一行被找出来了,可为啥1234.234.04.5678也被找出来了吗?因为grep找的是包蕴某一格局的行,这一行包蕴二个合乎情势的字符串234.234.04.567。相反,123.4234.045.678这一行不分包符合情势的字符串,所以不会被找出来。
  • grep是一种检索过滤工具,正则表明式在grep中用来寻找符合方式的字符串。其实正则表明还有贰个相当首要的施用是验证用户输入是还是不是合法,例如用户通过网页表单提交本身的email地址,就需求用程序验证一下是否合法的email地址,那个工作能够在网页的javascript中做,也足以在网站后台程序中做,例如PHP、Perl、Python、Ruby、Java或C,所有那么些语言都协理正则表明式,可以说,近日不帮衬正则表达式的编程语言实在少见。除了编程语言之外,很多UNIX命令和工具也都援助正则表达式,例如grep、vi、sed、awk、emacs等等。“正则表明式”如同“变量”一样,它是一个大规模的定义,而不是某一种工具或编程语言的风味。

正则表明式

  • 开始我们用grep在3个文件中找出含有某个字符串的行,比如在头文件中找出2个宏定义。其实grep还足以找出适合某些方式(Pattern)的一类字符串。诸如找出装有符合xxx@xxx.xxx形式的字符串(也等于email地址),须求x字符可以是字母、数字、下划线、小数点或减号,email地址的每一片段可以有壹个或两个x字符,例如abc.d@ef.com、1_2@987-6.54,当然吻合那几个方式的不全是合法的email地址,但起码可以做一遍始发筛选,筛掉a.b、c@d等自然不是email地址的字符串。再比如,找出富有符合yyy-yyy-yyy-yyy形式的字符串(相当于IP地址),要求y是0-9的数字,IP地址的每一片段能够有1-二个y字符。
  • 如若用grep查找二个格局,怎样表示那几个形式,这一类字符串,而不是一定的字符串呢?从那五个大致的例证可以见见,要代表贰个格局至少应当包蕴以下音信:
  • 字符类(Character
    Class):如上例的x和y,它们在械中意味着3个字符,不过取值范围是一类字符中的任意多个。
  • 数量限定符(Quantifier):邮件地址的每壹个部分可以有二个或七个x字符,IP地址的每一有些可以有1-1个y字符。
  • 各个字符类以及普通字符之间的职务关系:例如邮件地址分三有的,用一般字符@和.隔开,IP地址分四局地,用.隔开,每一片段都足以字符类和数据限制符描述。为了表示地点关系,还有地方限定符(Anchor)的概念,将在底下介绍。
  • 确定部分破例语法表示字符类、数量限定符和岗位关系,然后用那些特种语法和常见字符一起表示七个形式,那就是正则表明式(Regular
    Expression)。例如email地址的正则表明式能够写成[a-zA-Z0-9.-]+@[a-zA-Z0-9.-]+.[a-zA-Z0-9_.-]+,IP地址的正则表达式能够写成[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}。下一节牵线正则表明式的语法,我们先看看正则表达式在grep中怎么用。例如有这么二个文书testfile:

    192.168.1.1
    1234.234.04.5678
    123.4234.045.678
    abcde
    
    $ egrep '[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}' testfile
    192.168.1.1
    1234.234.04.5678
    
  • egrep也等于grep
    -E,表示接纳Extended正则表达式语法。grep的正则表明式有Basic和Extended二种标准,它们之间的界别下一节再解释。其余还有fgrep命令,也等于grep
    -F,表示只搜索一定字符而不搜索正则表明式格局,不会按正则表明式的语法解释前面的参数。

  • 只顾正则表明式参数用单引号括起来了,因为正则表明式中用到的无数特殊字符在Shell中也有异样意义(例如),只有用单引号括起来才能确保这几个字符维持原状地传给grep命令,而不会被Shell解释掉。
  • 192.168.1.1顺应上述形式,由多少个.隔开的四段组成,每段都以1到壹个数字,所以这一行被找出来了,可怎么1234.234.04.5678也被找出来了呢?因为grep找的是带有某一形式的行,这一行包罗八个相符方式的字符串234.234.04.567。相反,123.4234.045.678这一行不分包符合方式的字符串,所以不会被找出来。
  • grep是一种检索过滤工具,正则表达式在grep中用来探寻符合情势的字符串。其实正则表明还有三个主要的施用是验证用户输入是或不是合法,例如用户通过网页表单提交本身的email地址,就要求用程序验证一下是还是不是法定的email地址,这一个工作可以在网页的javascript中做,也足以在网站后台程序中做,例如PHP、Perl、Python、Ruby、Java或C,所有那几个语言都支持正则表明式,可以说,近期不辅助正则表明式的编程语言实在少见。除了编程语言之外,很多UNIX命令和工具也都协助正则表明式,例如grep、vi、sed、awk、emacs等等。“正则表明式”如同“变量”一样,它是一个广阔的定义,而不是某一种工具或编程语言的特点。

Shell脚本调试方法

  • Shell提供了一些用来调试脚本的选项,如:

    -n      读一遍脚本中的命令但不执行,用于检查脚本中的语法错误。
    -v      一边执行脚本, 一边将执行过的脚本命令打印到标准错误输出。
    -x      提供跟踪执行信息,将执行的每一条命令和结果依次打印出来。
    
  • 那个接纳有三种普遍的利用办法:

  • 1、在命令行提供参数。如:

    $ sh -x ./script.sh
    
  • 2、在剧本开关提供参数。如:

    #! /bin/sh -x
    
  • 叁,在本子中用set命令运营或剥夺参数。如:

    #! /bin/sh
    
    if [ -z "$1" ]; then
        set -x
        echo "ERROR: Insufficient Args."
        exit 1
        set +x
    fi
    
  • set -x和set
    +x分别表示启用或剥夺-x参数,那样可以只对台本中的某一段进展跟踪调试。

表达式

贰个awk表明式可以由数值、字符常量、变量、操作符、函数和正则表明式自由组合而成。

运算符 意义
+
*
/
%
^或** 乘方
++x 在返回x之前,x变量加1
x++ 在返回x之后,x变量加1
wsx@wsx-ubuntu:~/桌面$ awk '/^$/{print x+=1}' input
1
2
3
4
5

宗旨语法

  • 咱俩知道C的变量和Shell脚本变量的概念和运用方法很不等同,表明能力也不等同,C的变量有各样别型,而Shell脚本变量都是字符串。同样道理,各样工具和编程语言所利用的正则表明式规范的语法并不同,表达能力也各差距,有的正则表明式规范引入很多扩大,能发布更扑朔迷离的形式,但各个正则表明式规范的基本概念都以想通的。本节介绍egrep(1)所采用的正则表达式,它大体上符合POSIX正则表明式规范,详见regex(7)(看这些man
    page对你的英文相对是很好的陶冶)。希望读者仿照上一节的例子,一边读书语法,一边用egrep命令做尝试。
  • 字符类
    • .协作任意三个字符,abc.可以匹配abcd、abc9等。
    • []匹配括号中的任意两个字符,[abc]d可以匹配ad、bd或cd。
    • -在[]括号内代表字符范围,[0-9a-fA-F]可以匹配一人十六进制数字。
    • ^位于[]括号内的先导,匹配括号中的字符之外的随意3个字符,[^xy]匹配xy之外的任一字符,由此[^xy]1可以匹配a一,b1但不匹配x1、y1。
    • [[:xxx:]]grep工具预约义的有的命名字符类,[[:alpha:]]同盟二个字母,[[:digit:]]匹配3个数字。
  • 数据限定符

    • ?紧跟在它面前的单元匹配零次或两回,[0-9]?\.[0-9]匹配0.0、2.三,.5等,由于.在正则表达式中是2个特殊字符,所以需求用\转义一下,取字面值。
    • +紧跟在它前边的单元应十分四遍或频仍,[a-zA-Z0-9_.-]+@[a-zA-Z0-9_.-]+\.[a-zA-Z0-9_.-]+匹配email地址。
    • *紧跟在它前边的单元应协作零次或频仍,[0-9][0-9]*匹配至少1个数字,等价于[0-9]+[a-zA-Z_]+[a-zA-Z_0-9]*匹配C语言的标识符。
    • {N}紧跟在它面前的单元应规范匹配N次,[1-9][0-9]{2}匹配从100到999的整数。
    • {N,}紧跟在它面前的单元应同盟至少N次,[1-9][0-9]{2,}合营四位以上(含多少人)的平头。
    • {,M}紧跟在它面前的单元应合作最多M次,[0-9]{,1}相当于[0-9]?
    • {N,M}紧跟在它面前的单元应非常至少次,最多M次,[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}匹配IP地址。
    • 再一次注意:grep找的是含有某一方式的行,而不是全然合作某一形式的行
    • 比如有如下文本:

        aaabc
        aad
        efg
      
    • 查找a*本条形式的结果,会发现,三行都被找了出去。

        $ egrep 'a*' testfile
        aaabc
        aad
        efg
      
    • a匹配0个或多个a,而第三行包罗0个a,所以也蕴藏了这一形式。单独用a那样的正则说明式做查找没什么意思,一般是把a*用作正则表明式的一有个别来用。

  • 义务限定符

    • ^合作行首的地点,^Content匹配位于一行开始的Content。
    • $匹配行末的地方,;$格外位于一行结尾的;号,^$匹配空行。
    • \<同盟单词开关的岗位,\<th匹配…
      this,但不匹配ethernet、tenth。
    • \>格外单词结尾的岗位,p\>匹配leap
      …,但不匹配parent、sleepy。
    • \b合作单词开关或最终的任务,\bat\b匹配… at
      …,但不匹配cat、atexit、batch。
    • \B匹配非单词开端和终极的职位,\Bat\B匹配battery,但不匹配…
      attend、hat …
    • 职位限定符可以匡助grep更规范地搜索。
    • 譬如说上一节大家用[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}找寻IP地址,找到那两行

        192.168.1.1
        1234.234.04.5678
      
    • 如果用^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$搜索,就可以1234.234.04.5678这一行过滤掉了。

  • 别的特殊字符

    • \转义字符,普通字符转义为特殊字符,特殊字符转义为平日字符。普通字符<写成<表示单词开头的职责,特殊字符.写成.以及\写成\就作为普通字符来同盟。
    • ()将正则表明式的一部分括起来组成贰个单元,可以对整个单元使用数据限定符。([0-9]{1,3}\.){3}[0-9]{1,3}匹配IP地址
    • |接连三个子表明式,表示或的关系。n(o|either)匹配no或neither

大旨语法

  • 咱俩知道C的变量和Shell脚本变量的概念和使用格局很不一致,表明能力也不雷同,C的变量有各种类型,而Shell脚本变量都以字符串。同样道理,种种工具和编程语言所使用的正则表明式规范的语法并不相同,表达能力也各不相同,有的正则说明式规范引入很多增添,能公布更扑朔迷离的情势,但种种正则表明式规范的基本概念皆以想通的。本节介绍egrep(1)所拔取的正则表明式,它大体上符合POSIX正则表明式规范,详见regex(7)(看那几个man
    page对您的英文相对是很好的磨练)。希望读者仿照上一节的事例,一边上学语法,一边用egrep命令做尝试。
  • 字符类
    • .匹配任意贰个字符,abc.可以匹配abcd、abc9等。
    • []匹配括号中的任意2个字符,[abc]d可以匹配ad、bd或cd。
    • -在[]括号内表示字符范围,[0-9a-fA-F]可以合营一位十六进制数字。
    • ^位于[]括号内的初始,匹配括号中的字符之外的随机3个字符,[^xy]匹配xy之外的任一字符,由此[^xy]1能够匹配a一,b1但不匹配x一,y1。
    • [[:xxx:]]grep工具预约义的局地命名字符类,[[:alpha:]]匹配贰个字母,[[:digit:]]特出一个数字。
  • 数码限定符

    • ?紧跟在它面前的单元匹配零次或五回,[0-9]?\.[0-9]匹配0.0、2.三,.5等,由于.在正则表明式中是三个特殊字符,所以须求用\转义一下,取字面值。
    • +紧跟在它前面的单元应协作五次或频繁,[a-zA-Z0-9_.-]+@[a-zA-Z0-9_.-]+\.[a-zA-Z0-9_.-]+匹配email地址。
    • *紧跟在它面前的单元应出色零次或频仍,[0-9][0-9]*万分至少3个数字,等价于[0-9]+[a-zA-Z_]+[a-zA-Z_0-9]*匹配C语言的标识符。
    • {N}紧跟在它面前的单元应准确匹配N次,[1-9][0-9]{2}匹配从100到999的整数。
    • {N,}紧跟在它后面的单元应合作至少N次,[1-9][0-9]{2,}十分肆人以上(含三位)的平头。
    • {,M}紧跟在它后面的单元应同盟最多M次,[0-9]{,1}相当于[0-9]?
    • {N,M}紧跟在它前边的单元应卓殊至少次,最多M次,[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}匹配IP地址。
    • 双重注意:grep找的是带有某一形式的行,而不是完全匹配某一格局的行
    • 比如说有如下文本:

      aaabc
      aad
      efg
      
    • 查找a*以此形式的结果,会发现,三行都被找了出去。

      $ egrep 'a*' testfile
      aaabc
      aad
      efg
      
    • a匹配0个或三个a,而第三行包蕴0个a,所以也包括了这一格局。单独用a那样的正则表明式做查找没什么意义,一般是把a*作为正则表明式的一部分来用。

  • 岗位限定符

    • ^非凡行首的职位,^Content合作位于一行先河的Content。
    • $匹配行末的职位,;$十分位于一行结尾的;号,^$匹配空行。
    • \<合作单词开关的职位,\<th匹配…
      this,但不匹配ethernet、tenth。
    • \>万分单词结尾的职位,p\>匹配leap
      …,但不匹配parent、sleepy。
    • \b匹配单词开关或末了的地方,\bat\b匹配… at
      …,但不匹配cat、atexit、batch。
    • \B匹配非单词伊始和尾声的职务,\Bat\B匹配battery,但不匹配…
      attend、hat …
    • 职分限定符能够帮忙grep更确切地寻找。
    • 譬如上一节我们用[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}寻找IP地址,找到那两行

      192.168.1.1
      1234.234.04.5678
      
    • 如果用^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$摸索,就可以1234.234.04.5678这一行过滤掉了。

  • 其余特殊字符

    • \转义字符,普通字符转义为特殊字符,特殊字符转义为普通字符。普通字符<写成<表示单词开始的岗位,特殊字符.写成.以及\写成\就当做普通字符来合营。
    • ()将正则表明式的一部分括起来组成多个单元,可以对全部单元使用数据限定符。([0-9]{1,3}\.){3}[0-9]{1,3}匹配IP地址
    • |一而再八个子表达式,表示或的关联。n(o|either)匹配no或neither

正则表明式

  • 先前小编们用grep在壹个文书中找出含有有个别字符串的行,比如在头文件中找出一个宏定义。其实grep还是能找出适合某些方式(Pattern)的一类字符串。例如找出所有符合[email protected]格局的字符串(相当于email地址),须求x字符可以是字母、数字、下划线、小数点或减号,email地址的每一片段可以有1个或八个x字符,例如[email protected]、[email protected],当然吻合那个情势的不全是合法的email地址,但最少可以做四遍开首筛选,筛掉a.b、[email protected]等自然不是email地址的字符串。再比如说,找出装有符合yyy-yyy-yyy-yyy格局的字符串(相当于IP地址),必要y是0-9的数字,IP地址的每一局地可以有1-三个y字符。
  • 如若用grep查找2个形式,如何表示这一个格局,这一类字符串,而不是特定的字符串呢?从那多个大约的例证可以看看,要表示多少个格局至少应该包含以下消息:
  • 字符类(Character
    Class):如上例的x和y,它们在械中代表三个字符,不过取值范围是一类字符中的任意3个。
  • 数码限定符(Quantifier):邮件地址的每一个片段可以有2个或多少个x字符,IP地址的每一部分可以有1-贰个y字符。
  • 各个字符类以及平常字符之间的地点关系:例如邮件地址分三有的,用平时字符@和.隔开,IP地址分四局地,用.隔开,每一片段都得以字符类和数据限制符描述。为了表示地点关系,还有地点限定符(Anchor)的定义,将在底下介绍。
  • 确定部分出奇语法表示字符类、数量限定符和职位关系,然后用这么些出色语法和平凡字符一起表示几个形式,那就是正则表明式(Regular
    Expression)。例如email地址的正则表明式可以写成[a-zA-Z0-9.-][email protected][a-zA-Z0-9.-]+.[a-zA-Z0-9_.-]+,IP地址的正则说明式可以写成[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}。下一节牵线正则表达式的语法,大家先看看正则表达式在grep中怎么用。例如有诸如此类一个文本testfile:

    192.168.1.1
    1234.234.04.5678
    123.4234.045.678
    abcde
    
    $ egrep '[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}' testfile
    192.168.1.1
    1234.234.04.5678
    
  • egrep约等于grep
    -E,表示接纳Extended正则表明式语法。grep的正则表明式有Basic和Extended两种标准,它们中间的分别下一节再解释。别的还有fgrep命令,约等于grep
    -F,表示只搜索一定字符而不搜索正则表明式方式,不会按正则表明式的语法解释后边的参数。

  • 专注正则表达式参数用单引号括起来了,因为正则表达式中用到的成百上千特殊字符在Shell中也有卓殊意义(例如),唯有用单引号括起来才能确保那个字符纹丝不动地传给grep命令,而不会被Shell解释掉。

  • 192.168.1.1符合上述方式,由七个.隔开的四段组成,每段都以1到3个数字,所以这一行被找出来了,可为啥1234.234.04.5678也被找出来了吗?因为grep找的是包罗某一形式的行,这一行包罗三个顺应格局的字符串234.234.04.567。相反,123.4234.045.678这一行不分包符合形式的字符串,所以不会被找出来。
  • grep是一种检索过滤工具,正则表达式在grep中用来搜寻符合方式的字符串。其实正则表明还有一个首要的运用是认证用户输入是不是合法,例如用户通过网页表单提交自身的email地址,就须求用程序验证一下是否合法的email地址,那一个工作得以在网页的javascript中做,也足以在网站后台程序中做,例如PHP、Perl、Python、Ruby、Java或C,所有这一个语言都协助正则表明式,可以说,近期不襄助正则表明式的编程语言实在少见。除了编程语言之外,很多UNIX命令和工具也都协助正则表明式,例如grep、vi、sed、awk、emacs等等。“正则表明式”就好像“变量”一样,它是1个广阔的概念,而不是某一种工具或编程语言的特征。

系统变量

awk定义了过多内建变量用于安装条件音讯,我们称为系统变量。分为三种:一种用于转移awk的暗中认可值,例如域分隔符;第三种用于定义系统值,在拍卖公事时方可读取那一个系统值。

变量名 意义
$n 当前记录的第n个域,域用FS分隔
$0 记录的所有域
ARGC 命令行参数的数量
ARGIND 命令行中当前文件的位置(从0开始标号)
ARGV 命令行参数的数组
CONVFMT 数字转换格式
ENVIRON 环境变量关联数组
ERRNO 最后一个系统错误的描述
FIELDWIDTHS 字段宽度列表,以空格键分隔
FILENAME 当前文件名
FNR 浏览文件的记录数
FS 字段分隔符,默认是空格键
IGNORECASE 布尔变量,如果为真,则进行忽略大小写的匹配
NF 当前记录中的域数量
NR 当前记录数
OFMT 数字的输出格式
OFS 输出域分隔符,默认是空格键
ORS 输出记录分隔符,默认是换行符
RLENGTH 由match函数所匹配的字符串长度
RS 记录分隔符,默认是空格键
RSTART 由match函数所匹配的字符串的第1个位置
SUBSEP 数组下标分隔符,默认值是\034

Basic正则和Extended正则差异

  • 以上介绍的是grep正则表明式的Extended规范,Basic规范也有这么些语法,只是字符?+{}|()应表明为普通字符,要表示上述特殊含义则需求加\转义。若是用grep而不是egrep,并且不加-E参数,则应根据Basic规范来写正则表明式。

Basic正则和Extended正则分化

  • 如上介绍的是grep正则表达式的Extended规范,Basic规范也有那个语法,只是字符?+{}|()应表达为平日字符,要表示上述特殊含义则必要加\转义。假设用grep而不是egrep,并且不加-E参数,则应依据Basic规范来写正则表明式。

主导语法

  • 大家知道C的变量和Shell脚本变量的概念和行使办法很不平等,表明能力也不平等,C的变量有种种别型,而Shell脚本变量都以字符串。同样道理,各个工具和编程语言所利用的正则表明式规范的语法并不一样,表达能力也各不同,有的正则表明式规范引入很多恢弘,能表明更复杂的格局,但各样正则表明式规范的基本概念都以想通的。本节介绍egrep(1)所使用的正则表明式,它大约上符合POSIX正则表明式规范,详见regex(7)(看那个man
    page对你的英文相对是很好的陶冶)。希望读者仿照上一节的事例,一边学习语法,一边用egrep命令加强验。
  • 字符类
    • .卓殊任意三个字符,abc.可以匹配abcd、abc9等。
    • []匹配括号中的任意2个字符,[abc]d可以匹配ad、bd或cd。
    • -在[]括号内代表字符范围,[0-9a-fA-F]可以匹配一位十六进制数字。
    • ^位于[]括号内的发端,匹配括号中的字符之外的随机二个字符,[^xy]匹配xy之外的任一字符,因而[^xy]1可以匹配a1、b1但不匹配x1、y1。
    • [[:xxx:]]grep工具预订义的有的命名字符类,[[:alpha:]]匹配一个假名,[[:digit:]]极度一个数字。
  • 数据限定符

    • ?紧跟在它前边的单元匹配零次或一遍,[0-9]?\.[0-9]极度0.0、2.三,.5等,由于.在正则表明式中是3个特殊字符,所以需求用\转义一下,取字面值。
    • +紧跟在它面前的单元应卓越一遍或频仍,[a-zA-Z0-9_.-][email protected][a-zA-Z0-9_.-]+\.[a-zA-Z0-9_.-]+匹配email地址。
    • *紧跟在它前面的单元应非凡零次或频仍,[0-9][0-9]*优秀至少1个数字,等价于[0-9]+[a-zA-Z_]+[a-zA-Z_0-9]*匹配C语言的标识符。
    • {N}紧跟在它面前的单元应规范匹配N次,[1-9][0-9]{2}匹配从100到999的整数。
    • {N,}紧跟在它面前的单元应合作至少N次,[1-9][0-9]{2,}优良两人以上(含三个人)的平头。
    • {,M}紧跟在它面前的单元应格外最多M次,[0-9]{,1}相当于[0-9]?
    • {N,M}紧跟在它面前的单元应合营至少次,最多M次,[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}匹配IP地址。
    • 双重注意:grep找的是富含某一形式的行,而不是截然匹配某一格局的行
    • 比如说有如下文本:

      aaabc
      aad
      efg
      
    • 查找a*其一格局的结果,会发现,三行都被找了出来。

      $ egrep 'a*' testfile
      aaabc
      aad
      efg
      
    • a匹配0个或四个a,而第三行包罗0个a,所以也带有了这一情势。单独用a那样的正则表明式做查找没什么意义,一般是把a*用作正则表明式的一有的来用。

  • 地方限定符

    • ^万分行首的义务,^Content合作位于一行伊始的Content。
    • $合营行末的任务,;$匹配位于一行结尾的;号,^$匹配空行。
    • \<卓殊单词开关的职位,\<th匹配…
      this,但不匹配ethernet、tenth。
    • \>匹配单词结尾的职位,p\>匹配leap
      …,但不匹配parent、sleepy。
    • \b格外单词开关或最终的地点,\bat\b匹配… at
      …,但不匹配cat、atexit、batch。
    • \B协作非单词伊始和最终的岗位,\Bat\B匹配battery,但不匹配…
      attend、hat …
    • 岗位限定符能够帮衬grep更确切地查找。
    • 诸如上一节大家用[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}搜寻IP地址,找到那两行

      192.168.1.1
      1234.234.04.5678
      
    • 如果用^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$查找,就足以1234.234.04.5678这一行过滤掉了。

  • 任何特殊字符

    • \转义字符,普通字符转义为特殊字符,特殊字符转义为普通字符。普通字符<写成\<表示单词发轫的职分,特殊字符.写成.以及\写成\就当作普通字符来协作。
    • ()将正则表达式的一部分括起来组成1个单元,可以对所有单元使用数据限定符。([0-9]{1,3}\.){3}[0-9]{1,3}匹配IP地址
    • |连天多少个子表明式,表示或的关联。n(o|either)匹配no或neither

格式化输出

awk借鉴C语言的语法,定义了printf输出语句。基本语法如下:

printf(格式控制符, 参数)

格式控制符分为修饰符和格式符三种,如下:

修饰符 意义
左对齐
width 域的步长
.prec 小数点右边的位数
运算符 意义
%c ASCII字符
%d 整型数
%e 浮点数,科学计数法
%f 浮点数
%o 八进制数
%s 字符串
%x 十六进制数

grep

  • 1、作用
    • Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表明式搜索文件,并把匹配的行打印出来。grep全称是Global
      Regular Expression
      Print,表示全局正则表明式版本,它的运用权限是装有用户。
    • grep家族包蕴grep、egrep和fgrep。egrep和fgrep的指令只跟grep有很小不一致。egrep是grep的增加,匡助越来越多的re元字符,fgrep就是fixed
      grep和fast
      grep,它们把持有的假名都作为单词,相当于说,正则表明式中的元字符表示回其自小编的字面意思,不再新鲜。linux使用GNU版本的grep。它功用更强,能够因此-G、-E、-F命令选项来采用egrep和fgerp的效益。
  • 2、格式及主要参数
    • grep [option]
    • 首要参数:grep -help可查看
      • -c:只输出匹配行的计数。
      • -i:不区分轻重缓急写。
      • -h:查询多文件时不突显文件名。
      • -l:查询多文本时只输出包括匹配字符的公文名。
      • -n:突显匹配行及行号。
      • -s:不突显不存在或无匹配文本的错误音信。
      • -v:突显不分包匹配文本的享有行。
      • –color=auto:可以将找到的机要词部分加上颜色的显示。
    • pattern正则表达式首要参数:
      • :忽略正则表明式中特殊字符的本来面目含义。
      • ^:匹配正则表明式的始发行
      • $:匹配正则表明式的终止行
      • <:从匹配正则表明式的行初阶
      • >:到卓绝正则表明式的行终止
      • []:单个字符,如[A]即A符合必要
      • [ – ]:范围,如[A-Z],即A、B、C一贯到Z都符合需求。
      • .:所有的单个字符。
      • *:所有字符,长度可以为0。
  • 三,grep命令使用简便实例

      $ grep 'test' d*            显示所有以d开头的文件中包含test的行。
    

grep

  • 1、作用
    • Linux系统中grep命令是一种强大的文书搜索工具,它能采纳正则表明式搜索文件,并把匹配的行打印出来。grep全称是Global
      Regular Expression
      Print,表示全局正则表明式版本,它的应用权限是具有用户。
    • grep家族包涵grep、egrep和fgrep。egrep和fgrep的一声令下只跟grep有很小分歧。egrep是grep的增加,协理越来越多的re元字符,fgrep就是fixed
      grep和fast
      grep,它们把具有的假名都用作单词,也等于说,正则表明式中的元字符表示回其自身的字面意义,不再新鲜。linux使用GNU版本的grep。它功用更强,可以透过-G、-E、-F命令选项来接纳egrep和fgerp的职能。
  • 2、格式及主要参数
    • grep [option]
    • 主要参数:grep -help可查看
      • -c:只输出匹配行的计数。
      • -i:不区分轻重缓急写。
      • -h:查询多文本时不呈现文件名。
      • -l:查询多文本时只输出包罗匹配字符的公文名。
      • -n:显示匹配行及行号。
      • -s:不显得不存在或无匹配文本的错误新闻。
      • -v:显示不分包匹配文本的持有行。
      • –color=auto:可以将找到的根本词部分加上颜色的来得。
    • pattern正则表明式主要参数:
      • :忽略正则表达式中特殊字符的原本含义。
      • ^:匹配正则表明式的启幕行
      • $:匹配正则表明式的了断行
      • <:从匹配正则表明式的行开头
      • >:到格外正则表达式的行终止
      • []:单个字符,如[A]即A符合必要
      • [ – ]:范围,如[澳门金沙国际,A-Z],即A、B、C一贯到Z都符合必要。
      • .:所有的单个字符。
      • *:所有字符,长度可以为0。
  • 3、grep命令使用简易实例

    $ grep 'test' d*            显示所有以d开头的文件中包含test的行。
    

Basic正则和Extended正则差别

  • 以上介绍的是grep正则表明式的Extended规范,Basic规范也有那些语法,只是字符?+{}|()应表达为一般字符,要表示上述特殊意义则必要加\转义。即便用grep而不是egrep,并且不加-E参数,则应根据Basic规范来写正则表明式。

置于字符串函数

awk提供了有力的内置字符串函数,用于落到实处文件的字符串替换、查找以及分隔等效果,下表列出:

函数名 意义
gsub(r,s) 在输入文件中用s替换r
gsub(r,s,t) 在t中用s替换r
index(s,t) 返回s中字符串第一个t的位置
length(s) 返回s的长度
match(s,t) 测试s是否包含匹配t的字符串
split(r,s,t) 在t上将r分为序列s
sub(r,s,t) 将t中第1次出现的r替换为s
substr(r,s) 返回字符串r中从s开始的后缀部分
substr(r,s,t) 返回字符串r中从s开始长度为t的后缀部分

find

  • 鉴于find具有强有力的意义,所以它的选项也很多,其中一大半增选都值得我们花时间来精通一下。尽管系统中包括互连网文件系统(NFS),find命令在该文件系统中相同有效,只要您富有相应的权能。
  • 在运维二个不胜消耗财富的find命令时,很三人都赞成于把它置身后台执行,因为遍历三个大的文件系统恐怕会开支非常短的小运(那里是指30G字节以上的文件系统)。
  • 一、find命令格式

    • 一,find命令的一般格局为

      find pathname -options [-print -exec -ok …]

    • 二,find命令的参数

      • pathname:find命令所查找的目录路径。例如用.来表示当前目录,用/来代表系统根目录,递归查找。
      • -print:find命令将匹配的文件输出到正规输出。
      • -exec:find命令对才子佳人的文件执行该参数所提交的shell命令。相应命令的款型为’command’
        {} ;,注意{}内部无空格,和;之间含有3个空格分隔符。
      • -ok:和-exec的成效一样,只不过以一种尤其安全的情势来推行该参数所提交的shell命令,在推行每贰个指令此前,都会付出提示,让用户来规定是否执行。
    • 三,find命令选项
      • -name:根据文件名查找文件。
      • -perm:依据文件权限来查找文件。
      • -prune:使用这一选项可以使find命令不在当前指定的目录中检索,即使还要利用-depth选项,那么-prune将被find命令忽略。
      • -user:依照文件属主来查找文件。
      • -group:根据文件所属的组来查找文件。
      • -mtime -n
        +n:依据文件的变动时间来查找文件,-n代表文件更改时间距未来n天以内,+n表示文件更改时间间隔今后n天在此以前。find命令还有-atime和-ctime选项,但它们都有-mtime选项。
      • -nogroup:查找无有效属组的文本,即该文件所属的组在/etc/groups中不设有。
      • -nouser:查找无有效属主的文本,即该文件的属主在/etc/passwd中不设有。
      • newer file1 !
        file2:查找更改时间比文件file1新但比文件file2旧的文本。
      • -type:查找某一项目标文书,诸如:
        • b:块设备文件
        • d:目录
        • c:字符设备文件
        • p:管道文件
        • l:符号链接文件
        • f:普通文书
      • -size
        n:[c]查找文件长度为n块的文件,带有c时表示文件长度以字节计。
      • -depth:在查找文件时,首先查找当前目录中的文件,然后再在其子目录中摸索。
      • fstype:查找位于某一种类文件系统中的文件,那么些文件系统类型一般可以在配置文件/etc/fstab中找到,该配置文件中包括了本系统中关于文件系统的新闻。
      • mount 在查找文件时不当先文件系统mount点。
      • follow
        借使find命令碰到符号链接文件,就跟踪至链接所针对的文件。
    • 除此以外,上面多个的分别:
      • -amin n 查找系统中最后n分钟访问的文书
      • -atime n 查找系统中最后n*24钟头访问的文书
      • -cmin n 查找系统中最后n分钟被改变文件状态的文件
      • -ctime n 查找系统中最终n*24时辰被更改文件状态的文书
      • -mmin n 查找系统中最终n分钟被转移文件数量的文件
      • -mtime n 查找系统中最终n*24钟头被转移文件数量的文件
    • 4、使用exec或ok来执行shell命令

      • 动用find时,只要把想要的操作写在二个文件里,就可以用exec来合作find查找,很有益于的。
      • 在有点操作系统中只同意-exec选项诸如ls或ls
        -l这样的命令。超过半数用户使用这一选项是为了探寻旧文件并剔除它们。提议在真的举办rm命令删除文件以前,最好先用ls命令看一下,确认它们是所有删除文件。
      • exec选项后边跟随着所要执行的通令或脚本,然后是一对儿{},3个空格和3个,最终是3个分公司。为了使用exec选项,必要求同时拔取print选项。若是证惠氏(Beingmate)下find命令,会意识该命令只输出从近期路线起的相对路径及文件名。
      • 比如说:为了用ls -l命令列出所匹配的文书,可以把ls
        -l命令放在find命令的-exec选项中

          $ find . -type f -exec ls -l {} \;
        
      • 地点的事例中,find命令匹配到了当前目录下的装有普通文书,并在-exec选项中采纳ls
        -l命令将它们列出。

      • 在/logs目录中寻找更改时间在三二十一日此前的文本并剔除它们:

          $ find logs -type f -mtime +5 -exec rm {} \;
        
      • 切记:在shell中用任何措施删除文件从前,应领先查看相应的文书,一定要小心!当使用诸如mv或rm命令时,可以利用-exec选项的平安方式。它将在对每种匹配到的文件操作以前提醒您。

      • 在底下的例证中,find命令在当前目录中追寻所有文件名以.LOG结尾、更改时间在七日上述的公文,并剔除它们,只不过在剔除此前先交由提醒。

          $ find . -name "*.conf" -mtime +5 -ok rm {} \;
          < rm ... ./conf/httpd.conf > ? n
        
      • 按y键删除文件,按n键不删除。

      • 别的格局的授命都足以在-exec选项中采取。
      • 在底下的例证中大家使用grep命令。find命令首先匹配所有文件名为”passwd*”的文本,例如passwd、passwd.old、passed.bak,然后实施grep命令看看在那么些文件中是或不是存在二个itcast用户。

          $ find /etc -name "passwd*" -exec grep "root" {} \; 
          root:x:0:0:root:/root:/bin/zsh
        
  • 二、find使用例子

      find ./ -name *.mp3
    
      find ./ -type f/d/p/c/b/s/l
    
      find ./ -size +3M -size -7M             默认单位:512B  0.5k  一个扇区大小 
    
      find ./ -size +47k -size -89k
    
      find ./ -maxdepth 2 -type d
    
      find ./ -maxdepth 1 -name "*.sh" -exec rm -r {} \;
    
      find ./ -maxdepth 1 -name "*.sh" -ok rm -r {} \;
    
      find ./ -maxdepth 1 -type f -print0 | xargs -0 ls -lh
    
      find ./ -name "*.gz" -mtime -5 -exec ls -lh {} /;
    

find

  • 出于find具有强有力的功效,所以它的选项也很多,其中绝一大半摘取都值得我们花时间来打探一下。即便系统中富含网络文件系统(NFS),find命令在该文件系统中一致有效,只要您抱有相应的权力。
  • 在运作3个那些消耗电源的find命令时,很三人都倾向于把它坐落后台执行,因为遍历贰个大的文件系统大概会费用不长的时日(那里是指30G字节以上的文件系统)。
  • 一、find命令格式

    • 1、find命令的一般格局为

      find pathname -options [-print -exec -ok …]

    • 2、find命令的参数

      • pathname:find命令所查找的目录路径。例如用.来表示当前目录,用/来表示系统根目录,递归查找。
      • -print:find命令将极度的公文输出到专业输出。
      • -exec:find命令对一双两好的文书举行该参数所提交的shell命令。相应命令的格局为’command’
        {} ;,注意{}内部无空格,和;之间含有两个空格分隔符。
      • -ok:和-exec的功用一样,只但是以一种特别安全的格局来施行该参数所提交的shell命令,在进行每2个下令以前,都会交到指示,让用户来确定是不是履行。
    • 三,find命令选项
      • -name:依照文件名查找文件。
      • -perm:按照文件权限来查找文件。
      • -prune:使用这一选项可以使find命令不在当前指定的目录中摸索,假设同时使用-depth选项,那么-prune将被find命令忽略。
      • -user:根据文件属主来查找文件。
      • -group:依据文件所属的组来查找文件。
      • -mtime -n
        +n:按照文件的改变时间来查找文件,-n代表文件更改时间距以后n天以内,+n表示文件更改时间间隔以往n天以前。find命令还有-atime和-ctime选项,但它们都有-mtime选项。
      • -nogroup:查找无有效属组的文件,即该公文所属的组在/etc/groups中不存在。
      • -nouser:查找无有效属主的文件,即该文件的属主在/etc/passwd中不设有。
      • newer file1 !
        file2:查找更改时间比文件file1新但比文件file2旧的文件。
      • -type:查找某一连串的文书,诸如:
        • b:块设备文件
        • d:目录
        • c:字符设备文件
        • p:管道文件
        • l:符号链接文件
        • f:普通文书
      • -size
        n:[c]查找文件长度为n块的文书,带有c时表示文件长度以字节计。
      • -depth:在查找文件时,首先查找当前目录中的文件,然后再在其子目录中搜寻。
      • fstype:查找位于某一项目文件系统中的文件,那些文件系统类型一般可以在布署文件/etc/fstab中找到,该配置文件中涵盖了本系统中关于文件系统的新闻。
      • mount 在查找文件时不超越文件系统mount点。
      • follow
        如若find命令遇到符号链接文件,就跟踪至链接所针对的文本。
    • 其余,上面多少个的不同:
      • -amin n 查找系统中最终n分钟访问的文件
      • -atime n 查找系统中最终n*24钟头访问的公文
      • -cmin n 查找系统中最后n分钟被改变文件状态的文本
      • -ctime n 查找系统中最终n*24小时被更改文件状态的公文
      • -mmin n 查找系统中最后n分钟被转移文件数量的文本
      • -mtime n 查找系统中最终n*24钟头被改动文件数量的文本
    • 4、使用exec或ok来执行shell命令

      • 使用find时,只要把想要的操作写在多少个文书里,就足以用exec来协作find查找,很便利的。
      • 在有个别操作系统中只同意-exec选项诸如ls或ls
        -l那样的吩咐。一大半用户使用这一选项是为着寻觅旧文件并剔除它们。指出在真的履行rm命令删除文件以前,最好先用ls命令看一下,确认它们是有所删除文件。
      • exec选项后边跟随着所要执行的命令或脚本,然后是一对儿{},二个空格和3个,最终是三个分店。为了使用exec选项,必必要同时采纳print选项。固然证惠氏(Beingmate)(Ausnutria Hyproca)下find命令,会意识该命令只输出从当下路线起的相对路径及文件名。
      • 比如:为了用ls -l命令列出所匹配的文本,可以把ls
        -l命令放在find命令的-exec选项中

        $ find . -type f -exec ls -l {} \;
        
      • 下边的事例中,find命令匹配到了当前目录下的持有普通文书,并在-exec选项中使用ls
        -l命令将它们列出。

      • 在/logs目录中检索更改时间在二十四日之前的公文并删除它们:

        $ find logs -type f -mtime +5 -exec rm {} \;
        
      • 难忘:在shell中用其余措施删除文件从前,应当先查占星应的文书,一定要小心!当使用诸如mv或rm命令时,可以选拔-exec选项的平安方式。它将在对各样匹配到的文件操作此前提醒您。

      • 在下边的例子中,find命令在当前目录中摸索所有文件名以.LOG结尾、更改时间在二八日以上的公文,并剔除它们,只可是在剔除以前先提交提醒。

        $ find . -name "*.conf" -mtime +5 -ok rm {} \;
        < rm ... ./conf/httpd.conf > ? n
        
      • 按y键删除文件,按n键不删除。

      • 别的款式的一声令下都可以在-exec选项中利用。
      • 在上面的事例中我们应用grep命令。find命令首先匹配所有文件名为”passwd*”的文书,例如passwd、passwd.old、passed.bak,然后实施grep命令看看在那么些文件中是还是不是存在3个itcast用户。

        $ find /etc -name "passwd*" -exec grep "root" {} \; 
        root:x:0:0:root:/root:/bin/zsh
        
  • 二、find使用例子

    find ./ -name *.mp3
    
    find ./ -type f/d/p/c/b/s/l
    
    find ./ -size +3M -size -7M             默认单位:512B  0.5k  一个扇区大小 
    
    find ./ -size +47k -size -89k
    
    find ./ -maxdepth 2 -type d
    
    find ./ -maxdepth 1 -name "*.sh" -exec rm -r {} \;
    
    find ./ -maxdepth 1 -name "*.sh" -ok rm -r {} \;
    
    find ./ -maxdepth 1 -type f -print0 | xargs -0 ls -lh
    
    find ./ -name "*.gz" -mtime -5 -exec ls -lh {} /;
    

grep

  • 1、作用
    • Linux系统中grep命令是一种强大的文书搜索工具,它能应用正则表达式搜索文件,并把匹配的行打印出来。grep全称是Global
      Regular Expression
      Print,表示全局正则表达式版本,它的采纳权力是有着用户。
    • grep家族包含grep、egrep和fgrep。egrep和fgrep的授命只跟grep有很小差距。egrep是grep的恢弘,帮忙越来越多的re元字符,fgrep就是fixed
      grep和fast
      grep,它们把装有的字母都当做单词,相当于说,正则表达式中的元字符表示回其自个儿的字面意思,不再新鲜。linux使用GNU版本的grep。它效率更强,可以经过-G、-E、-F命令选项来利用egrep和fgerp的作用。
  • 2、格式及首要参数
    • grep [option]
    • 主要参数:grep -help可查看
      • -c:只输出匹配行的计数。
      • -i:不区分轻重缓急写。
      • -h:查询多文件时不显示文件名。
      • -l:查询多文本时只输出包蕴匹配字符的公文名。
      • -n:显示匹配行及行号。
      • -s:不出示不设有或无匹配文本的错误音讯。
      • -v:突显不含有匹配文本的所有行。
      • –color=auto:可以将找到的最首要词部分加上颜色的显得。
    • pattern正则表明式主要参数:
      • \:忽略正则表明式中特殊字符的原有含义。
      • ^:匹配正则表明式的开头行
      • $:匹配正则表明式的扫尾行
      • \<:从匹配正则说明式的行开端
      • >:到相当正则表明式的行终止
      • []:单个字符,如[A]即A符合必要
      • [ – ]:范围,如[A-Z],即A、B、C一贯到Z都符合需求。
      • .:所有的单个字符。
      • *:所有字符,长度可以为0。
  • 叁,grep命令使用简易实例

    $ grep 'test' d*            显示所有以d开头的文件中包含test的行。
    

向awk脚本传递参数

awk脚本内的变量可以在命令行中进行赋值,完成向awk脚本传递参数,变量赋值放在脚本之后、输入文件此前,格式为:

awk脚本 parameter=value 输入文件

sed

  • sed意为流编辑器(Stream
    Editor),在Shell脚本和Makefile中作为过滤器使用特别普通,也等于把前边一个顺序的出口引入sed的输入,经过一文山会海编制命令转换为另一种格式输出。sed和vi都出自早期UNIX的ed工具,所以重重sed命令和vi的末行命令是一模一样的。
  • sed命令行的基本格式为:

      sed option 'script' file1 file2 ...
      sed option -f scriptfile file1 file2 ...
    
  • 选用含义:

        -n, --quiet, --silent
                       静默输出,默认情况下,sed程序在所有脚本指令执行完毕后,
                       将自动打印模式空间中的内容,这些选项可以屏蔽自动打印。
    
        -e 脚本, --expression=脚本
                       允许多个脚本指令被执行。
    
        -f 脚本文件, --file=脚本文件
                       从文件中读取脚本指令,对编写自动脚本程序来说很棒!
    
        --follow-symlinks
                       直接修改文件时跟随软链接
    
        -i[SUFFIX], --in-place[=SUFFIX]
                       直接修改源文件,经过脚本指令处理后的内容将被输出至源文件
                      (源文件被修改)慎用!
    
        -l N, --line-length=N
                       该选项指定l指令可能输出的行长度,l指令用于输出非打印字符。
    
        --posix
                       禁用GNU sed扩展功能。
    
        -r, --regexp-extended
                       在脚本指令中使用扩展正则表达式
    
        -s, --separate
                       默认情况下,sed将把命令行指定的多个文件名作为一个长的连续的输入流。
                       而GNU sed则允许把他们当作单独的文件,这样如正则表达式则不进行跨文件匹配。
    
        -u, --unbuffered
                       从输入文件读取最少的数据,更频繁的刷新输出
    
        -z, --null-data
                       separate lines by NUL characters
            --help     显示帮助文档
            --version  显示sed版本。
    
        - 如果没有 -e, --expression, -f 或 --file 选项,那么第一个非选项参数被视为
          sed脚本。其他非选项参数被视为输入文件,如果没有输入文件,那么程序将从标准
          输入读取数据。
    
  • 如上仅是sed程序本人的选项意义表达,至于实际的脚本指令(即对文件内容做的操作)前边大家会详细描述,那里大约介绍几个剧本指令操作作为sed程序的例证。

      a,  append          追加
      i,  insert          插入
      d,  delete          删除
      s,  substitution    替换
    
  • 如:$ sed "2a test" ./testfile在出口testfile内容的第二行后添加”test”。

      $ sed "2,5d" testfile
    
  • sed处理的文件既可以由专业输入重定向得到,也足以当命令行参数传入,命令行参数可以五回传入多个文本,sed会依次拍卖。sed的编纂命令可以直接当命令行参数传入,也足以写成3个本子文件然后用-f参数指定,编辑命令的格式为:

      /pattern/action
    
  • 内部pattern是正则表达式,action是编辑操作。sed程序一行一行读出待处理文件,倘使某一行与pattern匹配,则履行相应的action,即便一条命令没有pattern而唯有action,这一个action将功能于待处理文件的每一行。

  • 常用sed命令

      /pattern/p  打印匹配pattern的行
      /pattern/d  删除匹配pattern的行
      /pattern/s//pattern1/pattern2/  查找符合pattern的行,将该行第一个匹配pattern1的字符串替换为pattern2   
      /pattern/s//pattern1/pattern2/g  查找符合pattern的行,将该行所有匹配pattern1的字符串替换为pattern2
    
    • 采用p命令需求注意,sed是把待处理文件的内容及其处理结果一起输出到正式输出的,由此p命令表示除了把文件内容打印之外还附加打印五回匹配pattern的行。比如三个文件testfile的故事情节是

        123
        abc
        456
      
    • 打印其中包蕴abc的行

        $ sed '/abc/p' testfile
        123
        abc
        abc
        456
      
    • 要想只输出处理结果,应丰硕-n选项,那种用法约等于grep命令

        $ sed -n '/abc/p' testfile
        abc
      
    • 运用d命令就不要求-n参数了,比如删除含有abc的行

        $ sed 'abc/d' testfile
        123
        456
      
    • 只顾,sed命令不会修改原文件,删除命令只象征某个行不打印输出,而不是从原文件中除去。

    • 运用查找替换命令时,可以把匹配pattern1的字符串复制到pattern2中,比如:

        $ sed 's/bc/-&-/' testfile
        123
        a-bc-
        456
      
    • 再比如:

        $ sed 's/\([0-9]\)\([0-9]\)/-\1-~\2~/' testfile
        -1-~2~3
        abc
        -4-~5~6
      
    • pattern2中的\1意味着与pattern1的第3个()括号相匹配的内容,\2代表与pattern1的首个()括号相匹配的情节。sed专擅认同使用Basic正则表明式规范,如果指定了-r选项则使用Extended规范,那么()括号就不必转义了。如:

        $ sed -r 's/([0-9])([0-9])/-\1-~\2~/' testfile
      
    • 轮换截止后,所有行,含有接二连三数字的率先个数字前后都添加了”-“号;第二个数字前后都添加了“~”号。

    • 可以五遍指定多条不一致的更迭命令,用“;”隔开:

        $ sed 's/yes/no/; s/static/dhcp/' testfile
        注:使用分号隔开指令。
      
    • 也可以利用-e参数来指定区其余更迭命令,有多少个替换命令需添加多少个-e参数:

        $ sed -e 's/yes/no/' -e 's/static/dhcp/' testfile
        注:使用-e选项
      
    • 如果testfile的情节是

        <html><head><title>Hello World</title></head>
        <body>Welcome to the world of regexp!</body></html>
      
    • 现在要去掉所有的HTML标签,使出口结果为:

        Hello World
        Welcome to the world of regexp!
      
    • 咋办啊?假使用上边的通令

        $ sed 's/<.*>//g' testfile
      
    • 结果是七个空行,把拥有字符都过滤掉了。那是因为,正则表明式中的数量限制符会匹配尽大概长的字符串,那称为贪心的(Greedy)。比如sed在处理第一行时,<.*>匹配的并不是或那样的价签,而是

        <html><head><title>Hello World</title></head>
      
    • 诸如此类一整行,因为这一行开端是<,中间是多少个随机字符,末尾是>。那么那条命令怎么改才对吗?留给同学们想想。

sed

  • sed意为流编辑器(Stream
    Editor),在Shell脚本和Makefile中作为过滤器使用尤其平日,也等于把前边3个顺序的输出引入sed的输入,经过一密密麻麻编制命令转换为另一种格式输出。sed和vi都来源于早期UNIX的ed工具,所以众多sed命令和vi的末行命令是一致的。
  • sed命令行的骨干格式为:

    sed option 'script' file1 file2 ...
    sed option -f scriptfile file1 file2 ...
    
  • 慎选含义:

      -n, --quiet, --silent
                     静默输出,默认情况下,sed程序在所有脚本指令执行完毕后,
                     将自动打印模式空间中的内容,这些选项可以屏蔽自动打印。
    
      -e 脚本, --expression=脚本
                     允许多个脚本指令被执行。
    
      -f 脚本文件, --file=脚本文件
                     从文件中读取脚本指令,对编写自动脚本程序来说很棒!
    
      --follow-symlinks
                     直接修改文件时跟随软链接
    
      -i[SUFFIX], --in-place[=SUFFIX]
                     直接修改源文件,经过脚本指令处理后的内容将被输出至源文件
                    (源文件被修改)慎用!
    
      -l N, --line-length=N
                     该选项指定l指令可能输出的行长度,l指令用于输出非打印字符。
    
      --posix
                     禁用GNU sed扩展功能。
    
      -r, --regexp-extended
                     在脚本指令中使用扩展正则表达式
    
      -s, --separate
                     默认情况下,sed将把命令行指定的多个文件名作为一个长的连续的输入流。
                     而GNU sed则允许把他们当作单独的文件,这样如正则表达式则不进行跨文件匹配。
    
      -u, --unbuffered
                     从输入文件读取最少的数据,更频繁的刷新输出
    
      -z, --null-data
                     separate lines by NUL characters
          --help     显示帮助文档
          --version  显示sed版本。
    
      - 如果没有 -e, --expression, -f 或 --file 选项,那么第一个非选项参数被视为
        sed脚本。其他非选项参数被视为输入文件,如果没有输入文件,那么程序将从标准
        输入读取数据。
    
  • 如上仅是sed程序本人的选项职能表明,至于实际的脚本指令(即对文本内容做的操作)后边大家会详细描述,那里几乎介绍多少个剧本指令操作作为sed程序的例证。

    a,  append          追加
    i,  insert          插入
    d,  delete          删除
    s,  substitution    替换
    
  • 如:$ sed "2a test" ./testfile在出口testfile内容的第二行后添加”test”。

    $ sed "2,5d" testfile
    
  • sed处理的文件既可以由标准输入重定向拿到,也得以当命令行参数传入,命令行参数可以五遍传入多少个文件,sed会依次拍卖。sed的编写命令可以直接当命令行参数传入,也得以写成二个本子文件然后用-f参数指定,编辑命令的格式为:

    /pattern/action
    
  • 其间pattern是正则表明式,action是编制操作。sed程序一行一行读出待处理文件,假诺某一行与pattern匹配,则履行相应的action,假诺一条命令没有pattern而唯有action,那个action将成效于待处理文件的每一行。

  • 常用sed命令

    /pattern/p  打印匹配pattern的行
    /pattern/d  删除匹配pattern的行
    /pattern/s//pattern1/pattern2/  查找符合pattern的行,将该行第一个匹配pattern1的字符串替换为pattern2   
    /pattern/s//pattern1/pattern2/g  查找符合pattern的行,将该行所有匹配pattern1的字符串替换为pattern2
    
    • 采用p命令须求注意,sed是把待处理文件的始末及其处理结果一起输出到正式输出的,因而p命令表示除了把文件内容打印之外还额外打印两回匹配pattern的行。比如三个文本testfile的内容是

      123
      abc
      456
      
    • 打印其中涵盖abc的行

      $ sed '/abc/p' testfile
      123
      abc
      abc
      456
      
    • 要想只输出处理结果,应丰硕-n选项,那种用法约等于grep命令

      $ sed -n '/abc/p' testfile
      abc
      
    • 使用d命令就不必要-n参数了,比如删除含有abc的行

      $ sed 'abc/d' testfile
      123
      456
      
    • 留神,sed命令不会修改原文件,删除命令只象征某个行不打印输出,而不是从原文件中删去。

    • 使用查找替换命令时,可以把匹配pattern1的字符串复制到pattern2中,比如:

      $ sed 's/bc/-&-/' testfile
      123
      a-bc-
      456
      
    • 再比如:

      $ sed 's/\([0-9]\)\([0-9]\)/-\1-~\2~/' testfile
      -1-~2~3
      abc
      -4-~5~6
      
    • pattern2中的\1意味与pattern1的第三个()括号相匹配的始末,\2意味着与pattern1的首个()括号相匹配的内容。sed暗中认同使用Basic正则表明式规范,若是指定了-r选项则使用Extended规范,那么()括号就不用转义了。如:

      $ sed -r 's/([0-9])([0-9])/-\1-~\2~/' testfile
      
    • 轮换为止后,所有行,含有三番五次数字的率先个数字前后都添加了”-“号;第二个数字前后都添加了“~”号。

    • 能够一遍指定多条差别的替换命令,用“;”隔开:

      $ sed 's/yes/no/; s/static/dhcp/' testfile
      注:使用分号隔开指令。
      
    • 也足以应用-e参数来指定差其他交替命令,有几个替换命令需添加多少个-e参数:

      $ sed -e 's/yes/no/' -e 's/static/dhcp/' testfile
      注:使用-e选项
      
    • 借使testfile的始末是

      <html><head><title>Hello World</title></head>
      <body>Welcome to the world of regexp!</body></html>
      
    • 今日要去掉所有的HTML标签,使出口结果为:

      Hello World
      Welcome to the world of regexp!
      
    • 怎么办呢?假若用下边的下令

      $ sed 's/<.*>//g' testfile
      
    • 结果是几个空行,把富有字符都过滤掉了。那是因为,正则表明式中的数量限制符会匹配尽恐怕长的字符串,那名叫贪心的(Greedy)。比如sed在拍卖第一行时,<.*>匹配的并不是或

      诸如此类的竹签,而是

      <html><head><title>Hello World</title></head>
      
    • 如此一整行,因为这一行起始是<,中间是多少个随机字符,末尾是>。那么那条命令怎么改才对吧?留给同学们想想。

find

  • 是因为find具有强大的职能,所以它的选项也很多,其中绝大多数取舍都值得我们花时间来询问一下。尽管系统中涵盖互连网文件系统(NFS),find命令在该文件系统中平等有效,只要您所有相应的权位。
  • 在运作2个特别消功耗源的find命令时,很多人都辅助于把它座落后台执行,因为遍历贰个大的文件系统大概会开支十分短的时日(那里是指30G字节以上的文件系统)。
  • 一、find命令格式

    • 一,find命令的一般情势为

      find pathname -options [-print -exec -ok …]

    • 二,find命令的参数

      • pathname:find命令所查找的目录路径。例如用.来表示当前目录,用/来代表系统根目录,递归查找。
      • -print:find命令将匹配的文书输出到正式输出。
      • -exec:find命令对金童玉女的文书执行该参数所付出的shell命令。相应命令的形式为’command’
        {} \;,注意{}内部无空格,和\;之间含有三个空格分隔符。
      • -ok:和-exec的机能一样,只但是以一种越发安全的形式来推行该参数所付出的shell命令,在推行每2个指令从前,都会交到提醒,让用户来规定是或不是实施。
    • 叁,find命令选项

      • -name:依据文件名查找文件。
      • -perm:依据文件权限来查找文件。
      • -prune:使用这一选项可以使find命令不在当前点名的目录中寻找,若是同时采纳-depth选项,那么-prune将被find命令忽略。
      • -user:根据文件属主来查找文件。
      • -group:依照文件所属的组来查找文件。
      • -mtime -n
        +n:依照文件的改变时间来查找文件,-n代表文件更改时间距今后n天之内,+n表示文件更改时间距离以往n天以前。find命令还有-atime和-ctime选项,但它们都有-mtime选项。
      • -nogroup:查找无有效属组的文件,即该文件所属的组在/etc/groups中不设有。
      • -nouser:查找无有效属主的文件,即该公文的属主在/etc/passwd中不设有。
      • newer file1 !
        file2:查找更改时间比文件file1新但比文件file2旧的文书。
      • -type:查找某一类型的文件,诸如:
        • b:块设备文件
        • d:目录
        • c:字符设备文件
        • p:管道文件
        • l:符号链接文件
        • f:普通文书
      • -size
        n:[c]查找文件长度为n块的公文,带有c时表示文件长度以字节计。
      • -depth:在查找文件时,首先查找当前目录中的文件,然后再在其子目录中搜寻。
      • fstype:查找位于某一档次文件系统中的文件,这么些文件系统类型一般可以在配备文件/etc/fstab中找到,该配置文件中带有了本系统中关于文件系统的音讯。
      • mount 在查找文件时不超越文件系统mount点。
      • follow
        假如find命令遭遇符号链接文件,就跟踪至链接所针对的文件。
    • 除此以外,上面多少个的界别:

      • -amin n 查找系统中最终n分钟访问的文书
      • -atime n 查找系统中最终n*24钟头访问的文书
      • -cmin n 查找系统中末了n分钟被更改文件状态的文件
      • -ctime n 查找系统中最终n*24钟头被更改文件状态的文件
      • -mmin n 查找系统中最终n分钟被转移文件数量的公文
      • -mtime n 查找系统中最终n*24钟头被改动文件数量的公文
    • 4、使用exec或ok来执行shell命令

      • 利用find时,只要把想要的操作写在二个文件里,就足以用exec来同盟find查找,很便宜的。
      • 在稍微操作系统中只同意-exec选项诸如ls或ls
        -l那样的通令。大部分用户使用这一选项是为着追寻旧文件并剔除它们。提出在真的实施rm命令删除文件此前,最好先用ls命令看一下,确认它们是装有删除文件。
      • exec选项前面跟随着所要执行的授命或脚本,然后是一对儿{},2个空格和三个\,最终是三个分公司。为了使用exec选项,必必要同时接纳print选项。如若证实一下find命令,会发觉该命令只输出从方今路线起的相对路径及文件名。
      • 比如说:为了用ls -l命令列出所匹配的文书,可以把ls
        -l命令放在find命令的-exec选项中

        $ find . -type f -exec ls -l {} \;
        
      • 地点的事例中,find命令匹配到了当前目录下的装有普通文书,并在-exec选项中利用ls
        -l命令将它们列出。

      • 在/logs目录中检索更改时间在十5日在此之前的文本并删除它们:

        $ find logs -type f -mtime +5 -exec rm {} \;
        
      • 记住:在shell中用任何措施删除文件在此之前,应领先查六柱预测应的文件,一定要小心!当使用诸如mv或rm命令时,能够动用-exec选项的平安格局。它将在对各种匹配到的公文操作此前指示您。

      • 在底下的例子中,find命令在当前目录中搜索所有文件名以.LOG结尾、更改时间在3日上述的文书,并删除它们,只但是在剔除以前先交给提示。

        $ find . -name "*.conf" -mtime +5 -ok rm {} \;
        < rm ... ./conf/httpd.conf > ? n
        
      • 按y键删除文件,按n键不删除。

      • 其余格局的吩咐都可以在-exec选项中运用。
      • 在底下的事例中大家运用grep命令。find命令首先匹配所有文件名为”passwd*”的公文,例如passwd、passwd.old、passed.bak,然后实施grep命令看看在这么些文件中是还是不是留存三个itcast用户。

        $ find /etc -name "passwd*" -exec grep "root" {} \; 
        root:x:0:0:root:/root:/bin/zsh
        
  • 二、find使用例子

    find ./ -name *.mp3
    
    find ./ -type f/d/p/c/b/s/l
    
    find ./ -size +3M -size -7M             默认单位:512B  0.5k  一个扇区大小 
    
    find ./ -size +47k -size -89k
    
    find ./ -maxdepth 2 -type d
    
    find ./ -maxdepth 1 -name "*.sh" -exec rm -r {} \;
    
    find ./ -maxdepth 1 -name "*.sh" -ok rm -r {} \;
    
    find ./ -maxdepth 1 -type f -print0 | xargs -0 ls -lh
    
    find ./ -name "*.gz" -mtime -5 -exec ls -lh {} /;
    

基准语句和循环语句

看起来基本和C一样,框架如下——

if (条件表达式)
    动作1
[else
    动作2]

while(条件表达式)
    动作

do
    动作
while(条件表达式)

for(设置计数器初值; 测试计数器; 计数器变化)
    动作

awk

  • sed以行为单位处理公事,awk比sed强的地点在于不仅能以行为单位还是能以列为单位拍卖文件。awk缺省的行分隔符是换行,缺省的列分隔符是连接的空格和Tab,不过行分隔和列分隔符都足以自定义,比如/etc/passwd文件的每一行有好三个字段,字段之间以:分隔,就足以另行定义awk的列分隔符为:并以列为单位拍卖这一个文件。awk实际上是一门很复杂的脚本语言,还有像C语言一样的分支和循环结构,可是基本用法和sed类似,awk命令行的骨干形式为:

      awk option 'script' file1 file2 ...
      awk option -f scriptfile file1 file2 ...
    
  • 和sed一样,awk处理的文书既可以由专业输入重定向得到,也足以当命令行参数传入,编辑命令可以直接当命令行参数传入,也得以用-f参数指定贰个剧本文件,编辑命令的格式为:

      /pattern/{actions}
      condition{actions}
    
  • 和sed类似,pattern是正则表达式,actions是一密密麻麻操作。awk程序一行一行读出待处理公事,即使某一行与pattern匹配,或许满足condition条件,则执行相应的actions,即便一条awk命令唯有actions部分,则actions成效于待处理文件的每一行。比如文件testfile的内容表示某商厦的库存量:

      ProductionA 30
      ProductionB 76      
      ProductionC 55
    
  • 打印每一行的第二列:

      $ awk '{print $2;}' testfile
      30
      76
      55
    
  • 活动变量$壹,$2分级代表第一列、第二列等,类似于Shell脚本的岗位参数,而$0表示所有当前行。再比如说,如若某种产品的库存量低于75则在末行标注须求预定:

      $ awk '$2<75 {printf "%s\t%s\n", $0, "REORDER";} $2>=75 {print $0;}' testfile
      ProductionA 30 REORDER
      ProductionB 76      
      ProductionC 55 REORDER
    
  • 可知awk也有和C语言格外相似的printf函数。awk命令的condition部分还能是三个非凡的condition——BEGIN和END,对于各个待处理文件,BEGIN前面的actions在拍卖整个文件以前实施一回,END前边的actions在总体文件处理完现在执行五次。

  • awk命令能够像C语言一样选用变量(但不必要定义变量),比如计算3个文件中的空行数

      $ awk '/^ *$/ {x=x+1;} END {print x;}' testfile
    
  • 就好像Shell的环境变量一样,有个别awk变量是预约义的有异样意义的:

    • awk常用的内建变量

        FILENAME    当前输入文件的文件名,该变量是只读的
        NR          当前行的行号,该变量是只读的,R代表record
        NF          当前行所拥有的列数,该变量是只读的,F代表field
        OFS         输出格式的列分隔符,缺省是空格
        FS          输入文件的列分隔符,缺省是连续的空格和Tab
        ORS         输出格式的行分隔符,缺省是换行符
        RS          输入文件的行分隔符,缺省是换行符
      
  • 譬如打印系统中的用户帐号列表

      $ awk 'BEGIN {FS=":"} {print $1;}' /etc/passwd
    
  • awk也足以像C语言一样采取if/else、while、for控制结构。可自动增加学习。

awk

  • sed以行为单位处理公事,awk比sed强的地点在于不仅能以行为单位仍是可以以列为单位处理公事。awk缺省的行分隔符是换行,缺省的列分隔符是连连的空格和Tab,然则行分隔和列分隔符都足以自定义,比如/etc/passwd文件的每一行有几五个字段,字段之间以:分隔,就能够再度定义awk的列分隔符为:并以列为单位处理那个文件。awk实际上是一门很复杂的脚本语言,还有像C语言一样的支行和巡回结构,不过基本用法和sed类似,awk命令行的基本方式为:

    awk option 'script' file1 file2 ...
    awk option -f scriptfile file1 file2 ...
    
  • 和sed一样,awk处理的文本既可以由正规输入重定向得到,也可以当命令行参数传入,编辑命令可以直接当命令行参数传入,也足以用-f参数指定三个本子文件,编辑命令的格式为:

    /pattern/{actions}
    condition{actions}
    
  • 和sed类似,pattern是正则表明式,actions是一名目繁多操作。awk程序一行一行读出待处理文件,假使某一行与pattern匹配,大概满足condition条件,则实施相应的actions,如若一条awk命令唯有actions部分,则actions成效于待处理文件的每一行。比如文件testfile的内容表示某公司的库存量:

    ProductionA 30
    ProductionB 76      
    ProductionC 55
    
  • 打印每一行的第二列:

    $ awk '{print $2;}' testfile
    30
    76
    55
    
  • 电动变量$一,$三个别表示第一列、第二列等,类似于Shell脚本的职责参数,而$0表示所有当前行。再例如,如若某种产品的库存量低于75则在末行标注须要预定:

    $ awk '$2<75 {printf "%s\t%s\n", $0, "REORDER";} $2>=75 {print $0;}' testfile
    ProductionA 30 REORDER
    ProductionB 76      
    ProductionC 55 REORDER
    
  • 可知awk也有和C语言非凡相似的printf函数。awk命令的condition部分还足以是八个极度的condition——BEGIN和END,对于每一个待处理文件,BEGIN后边的actions在处理任何文件此前实施一回,END后边的actions在一切文件处理完将来执行两次。

  • awk命令可以像C语言一样拔取变量(但不须求定义变量),比如计算一个文本中的空行数

    $ awk '/^ *$/ {x=x+1;} END {print x;}' testfile
    
  • 如同Shell的环境变量一样,有个别awk变量是预约义的有例外意义的:

    • awk常用的内建变量

      FILENAME    当前输入文件的文件名,该变量是只读的
      NR          当前行的行号,该变量是只读的,R代表record
      NF          当前行所拥有的列数,该变量是只读的,F代表field
      OFS         输出格式的列分隔符,缺省是空格
      FS          输入文件的列分隔符,缺省是连续的空格和Tab
      ORS         输出格式的行分隔符,缺省是换行符
      RS          输入文件的行分隔符,缺省是换行符
      
  • 比如说打印系统中的用户帐号列表

    $ awk 'BEGIN {FS=":"} {print $1;}' /etc/passwd
    
  • awk也得以像C语言一样采取if/else、while、for控制结构。可自动增添学习。

sed

  • sed意为流编辑器(Stream
    Editor),在Shell脚本和Makefile中作为过滤器使用格外平凡,约等于把后面三个主次的出口引入sed的输入,经过一多级编制命令转换为另一种格式输出。sed和vi都源于早期UNIX的ed工具,所以众多sed命令和vi的末行命令是一模一样的。
  • sed命令行的为主格式为:

    sed option 'script' file1 file2 ...
    sed option -f scriptfile file1 file2 ...
    
  • 选用含义:

      -n, --quiet, --silent
                     静默输出,默认情况下,sed程序在所有脚本指令执行完毕后,
                     将自动打印模式空间中的内容,这些选项可以屏蔽自动打印。
    
      -e 脚本, --expression=脚本
                     允许多个脚本指令被执行。
    
      -f 脚本文件, --file=脚本文件
                     从文件中读取脚本指令,对编写自动脚本程序来说很棒!
    
      --follow-symlinks
                     直接修改文件时跟随软链接
    
      -i[SUFFIX], --in-place[=SUFFIX]
                     直接修改源文件,经过脚本指令处理后的内容将被输出至源文件
                    (源文件被修改)慎用!
    
      -l N, --line-length=N
                     该选项指定l指令可能输出的行长度,l指令用于输出非打印字符。
    
      --posix
                     禁用GNU sed扩展功能。
    
      -r, --regexp-extended
                     在脚本指令中使用扩展正则表达式
    
      -s, --separate
                     默认情况下,sed将把命令行指定的多个文件名作为一个长的连续的输入流。
                     而GNU sed则允许把他们当作单独的文件,这样如正则表达式则不进行跨文件匹配。
    
      -u, --unbuffered
                     从输入文件读取最少的数据,更频繁的刷新输出
    
      -z, --null-data
                     separate lines by NUL characters
          --help     显示帮助文档
          --version  显示sed版本。
    
      - 如果没有 -e, --expression, -f 或 --file 选项,那么第一个非选项参数被视为
        sed脚本。其他非选项参数被视为输入文件,如果没有输入文件,那么程序将从标准
        输入读取数据。
    
  • 如上仅是sed程序自己的选项意义表明,至于具体的台本指令(即对文件内容做的操作)后边大家会详细描述,那里差不离介绍几个剧本指令操作作为sed程序的例证。

    a,  append          追加
    i,  insert          插入
    d,  delete          删除
    s,  substitution    替换
    
  • 如:$ sed "2a test" ./testfile在出口testfile内容的第二行后添加”test”。

    $ sed "2,5d" testfile
    
  • sed处理的文件既可以由专业输入重定向得到,也足以当命令行参数传入,命令行参数可以五次传入多少个文件,sed会依次拍卖。sed的编纂命令可以一贯当命令行参数传入,也足以写成一个剧本文件然后用-f参数指定,编辑命令的格式为:

    /pattern/action
    
  • 个中pattern是正则表明式,action是编辑操作。sed程序一行一行读出待处理文件,假设某一行与pattern匹配,则履行相应的action,假设一条命令没有pattern而唯有action,这些action将成效于待处理文件的每一行。

  • 常用sed命令

    /pattern/p  打印匹配pattern的行
    /pattern/d  删除匹配pattern的行
    /pattern/s//pattern1/pattern2/  查找符合pattern的行,将该行第一个匹配pattern1的字符串替换为pattern2   
    /pattern/s//pattern1/pattern2/g  查找符合pattern的行,将该行所有匹配pattern1的字符串替换为pattern2
    
    • 采用p命令必要注意,sed是把待处理文件的内容及其处理结果一起输出到正式输出的,因而p命令表示除了把文件内容打印之外还附加打印一回匹配pattern的行。比如多个文件testfile的情节是

      123
      abc
      456
      
    • 打印其中饱含abc的行

      $ sed '/abc/p' testfile
      123
      abc
      abc
      456
      
    • 要想只输出处理结果,应丰盛-n选项,那种用法相当于grep命令

      $ sed -n '/abc/p' testfile
      abc
      
    • 运用d命令就不须要-n参数了,比如删除含有abc的行

      $ sed 'abc/d' testfile
      123
      456
      
    • 注意,sed命令不会修改原文件,删除命令只代表有个别行不打印输出,而不是从原文件中除去。

    • 行使查找替换命令时,能够把匹配pattern1的字符串复制到pattern2中,比如:

      $ sed 's/bc/-&-/' testfile
      123
      a-bc-
      456
      
    • 再比如:

      $ sed 's/\([0-9]\)\([0-9]\)/-\1-~\2~/' testfile
      -1-~2~3
      abc
      -4-~5~6
      
    • pattern2中的\1意味着与pattern1的首先个()括号相匹配的情节,\2代表与pattern1的第四个()括号相匹配的始末。sed私自承认使用Basic正则表达式规范,如果指定了-r选项则使用Extended规范,那么()括号就不必转义了。如:

      $ sed -r 's/([0-9])([0-9])/-\1-~\2~/' testfile
      
    • 轮换为止后,所有行,含有三番五次数字的首先个数字前后都添加了”-“号;第四个数字前后都添加了“~”号。

    • 可以三次指定多条不一样的替换命令,用“;”隔开:

      $ sed 's/yes/no/; s/static/dhcp/' testfile
      注:使用分号隔开指令。
      
    • 也足以行使-e参数来指定差其余替换命令,有多少个替换命令需添加多少个-e参数:

      $ sed -e 's/yes/no/' -e 's/static/dhcp/' testfile
      注:使用-e选项
      
    • 假使testfile的情节是

      <html><head><title>Hello World</title></head>
      <body>Welcome to the world of regexp!</body></html>
      
    • 明天要去掉所有的HTML标签,使输出结果为:

      Hello World
      Welcome to the world of regexp!
      
    • 如何是好吧?倘使用上面的下令

      $ sed 's/<.*>//g' testfile
      
    • 结果是三个空行,把具备字符都过滤掉了。那是因为,正则表明式中的数量限制符会匹配尽大概长的字符串,那叫做贪心的(Greedy)。比如sed在处理第一行时,<.*>匹配的并不是或这样的价签,而是

      <html><head><title>Hello World</title></head>
      
    • 这么一整行,因为这一行开头是<,中间是几个随机字符,末尾是>。那么那条命令怎么改才对吧?留给同学们想想。

数组

数组是储存一文山会海值的变量,可因此索引来访问数组的值,索引必要用中括号括起,数组的中坚格式为:

array[index]=value

花样和C一样,但awk数组无需定义数组类型和大小,可以从来赋值后选用。一般用在for循环中

for (variable in array)
    do somethng with array[variable]

愈来愈多操作可以查阅:http://man.linuxde.net/awk

参考:Linux
Shell编程——从初学到通晓(第2版)

C程序中使用正则

  • POSIX规定了正则表明式的C语言库函数,详见regex(3)。我们早已学习了众多C语言库函数的用法,读者应当有着本人看懂man手册的能力了。本章介绍了正则表达式在grep、sed、awk中的用法,学习要力所能及触类旁通,请读者依照regex(3)自个儿总计正则表明式在C语言中的用法,写一些签单的顺序,例如验证用户输入的IP地址或email地址格式是不是科学。
  • C语言处理正则表达式常用的函数有regcomp()、regexec()、regfree()、regerror(),一般分为多少个步骤,如下所示:
    • 一,编译正则表明式regcomp()
    • 贰,匹配正则表明式regexec()
    • 叁,释放正则表明式regfree()
  • 下边是对五个函数的详尽解释

    • 一,regcomp()那一个函数把指定的正则表明式pattern编译成一种特定的多少格式compiled,那样可以使相当更实用。函数regexec会动用那个数据在目的文本串中举行格局匹配。执行成功重回0。
      • int regcomp(regex_t *compiled, const char *pattern, int cflags)
      • regex_t:是三个结构休数据类型,用来存放编译后的正则表明式,它的成员re_nsub用来囤积正则表明式中的子正则表明式的个数,子正则表明式就是用圆括号包起来的一些表明式。
      • pattern:是指向我们写好的正则表明式的指针。
      • cflags有如下六个值只怕是它们或运算(|)后的值:
        • REG_EXTENDED:以功用尤为强大的增加正则表明式的法子开展匹配。
        • REG_ICASE:匹配字母时忽略大小写
        • REG_NOSUB:不用存储匹配后的结果,只回去是不是成功匹配。尽管设置该标志位,那么在regexec将忽略nmatch和pmatch三个参数。
        • REG_NEWLINE:识别换行符,那样’$’就足以从行尾起先匹配,’^’就可以从行的开关初叶匹配。
    • 二,当大家编译好正则表达式后,就足以用regexec匹配大家的目的文本串了,假使在编译正则表明式的时候从不点名cflags的参数为REG_NEWLINE,则暗中认同意况下是忽视换行符的,也等于把全部文本串当作一个字符串处理。

      • 履行成功再次回到0。
      • regmatch_t是一个结构体数据类型,在regex.h中定义:

          typedef struct {
              regoff_t rm_so;
              regoff_t rm_eo;
          } regmatch_t;
        
      • 成员rm_so存放匹配文本串在对象串中的起第一地点,rm_eo存放甘休地方。平常我们以数组的样式定义一组那样的社团。因为屡次大家的正则表明式中还蕴涵子正则表明式。数组0单元存放主正则表明式地点,前面的单元依次存放正则表达式地点。

      • int regexec(regex_t *compiled, char *string, size_t nmatch, regmatch_t matchptr[], int eflags)
        • compiled:是现已用regcomp函数编译好的正则表明式。
        • string:是目的文本串。
        • nmatch:是regmatch_t结构体数组的尺寸。
        • matchptr:regmatch_t类型的布局体数组,存放匹配文本串的职位新闻。
        • eflags有七个值:
          • REG_NOTBOL:让优良字符^无效劳。
          • REG_NOTEOL:让特出字符$无效果。
    • 三,当大家运用完编译好的正则表达式后,大概要重新编译其余正则表明式的时候,大家能够用那个函数清空compiled指向的regex_t结构体的内容,请记住,如果是双重编译的话,一定要先清空regex_t结构体。

      • void regfree(regex_t *compiled)
    • 四,当执行regcomp或然regexec发生错误的时候,就可以调用这么些函数而回到多个包含错误新闻的字符串。
      • size_t regerror(int errcode, regex_t *compiled, char *buffer, size_t length)
        • errcode:是由regcomp和regexec函数再次回到的错误代号。
        • compiled:是早已用regcomp函数编译好的正则表达式,这些值可以为NULL。
        • buffer:指向用来存放在错误新闻的字符串的内存空间。
        • length:指明buffer的长度,假若那么些错误信息的尺寸当先这么些值,则regerror函数会活动截断超出的字符串,但他如故会回来完整的字符串的长度。所以我们可以用如下的点子先拿走错误字符串的尺寸。
        • 例如:size_t length = regerror(errcode, compiled, NULL, 0);
    • 测试用例:

        #include <sys/types.h>
        #include <regex.h>
        #include <stdio.h>
      
        int main(int argc, char *argv[])
        {
            if(argc != 3){ 
                printf("Usage: %s RegexString And Text\n", argv[0]);
            }   
      
            const char * p_regex_str = argv[1];
            const char * p_txt = argv[2];
            //编译后的结构体
            regex_t oregex;
            int ret = 0;
            //保存错误信息的数组
            char emsg[1024] = {0};
            size_t emsg_len = 0;
      
            //编译正则表达式, 扩展正则
            if((ret = regcomp(&oregex, p_regex_str, REG_EXTENDED|REG_NOSUB)) == 0){ 
                //执行匹配,不保存匹配的返回值
                if((ret = regexec(&oregex, p_txt, 0, NULL, 0)) == 0){ 
                    printf("%s matches %s\n", p_txt, p_regex_str);
                    regfree(&oregex);
                    return 0;
                }   
            }   
      
            //正则编译错误,存emsg中错误描述
            emsg_len = regerror(ret, &oregex, emsg, sizeof(emsg));
            //错误信息较长特殊情况
            emsg_len = emsg_len < sizeof(emsg)? emsg_len : sizeof(emsg) - 1;
      
            emsg[emsg_len] = '\0';
            printf("Regex error Msg: %s\n", emsg);
      
            regfree(&oregex);
      
            //非正常退出                                                                                             
            return 1;
        }
      
    • 非凡网址:

        ./a.out "http:\/\/www\..*\.com" "http://www.taobao.com"
      
    • 匹配邮箱:

        ./a.out "^[a-zA-Z0-9.]+@[a-zA-Z0-9]+.[a-zA-Z0-9]+" "abc.123@126.com"
        ./a.out "\w+([-+.]\w+)*@\w+([-+.]\w+)*\.\w+([-+.]\w+)*" "abc@qq.com"
      
    • 极度固话号码:请同学们本身编辑。

    • 除外GNU提供的函数外,还常用PCRE处理正则,全称是Rerl Compatible
      Regular
      Expressions。从名字我们可以看看PCRE库是与Perl中正则表达式相匹配的三个正则表达式库。PCRE是免费开源的库,它是由C语言完结的,那里是它的官方主页:
    • PCRE++是二个对PCRE库的C++封装,它提供了更进一步便宜、易用的C++接口。那里是它的官方主页:

C程序中应用正则

  • POSIX规定了正则表达式的C语言库函数,详见regex(3)。大家早就学习了众多C语言库函数的用法,读者应当拥有本人看懂man手册的能力了。本章介绍了正则表达式在grep、sed、awk中的用法,学习要可以触类旁通,请读者依据regex(3)本人总括正则表达式在C语言中的用法,写一些签单的先后,例如验证用户输入的IP地址或email地址格式是还是不是正确。
  • C语言处理正则表明式常用的函数有regcomp()、regexec()、regfree()、regerror(),一般分为五个步骤,如下所示:
    • 壹,编译正则表明式regcomp()
    • 2、匹配正则表明式regexec()
    • 三,释放正则表明式regfree()
  • 下边是对七个函数的详实分解

    • 1、regcomp()那些函数把指定的正则表明式pattern编译成一种特定的数据格式compiled,这样可以使相当更实用。函数regexec会采纳这一个数目在目的文本串中展开方式匹配。执行成功再次来到0。
      • int regcomp(regex_t *compiled, const char *pattern, int cflags)
      • regex_t:是1个结构休数据类型,用来存放在编译后的正则表达式,它的分子re_nsub用来储存正则表达式中的子正则表明式的个数,子正则表达式就是用圆括号包起来的一对表达式。
      • pattern:是指向我们写好的正则表明式的指针。
      • cflags有如下五个值只怕是它们或运算(|)后的值:
        • REG_EXTENDED:以效益越来越强硬的恢弘正则表明式的点子进行匹配。
        • REG_ICASE:匹配字母时忽略大小写
        • REG_NOSUB:不用存储匹配后的结果,只回去是不是成功匹配。即使设置该标志位,那么在regexec将忽略nmatch和pmatch多少个参数。
        • REG_NEWLINE:识别换行符,那样’$’就足以从行尾初叶匹配,’^’就能够从行的开关开始匹配。
    • 2、当大家编译好正则表明式后,就可以用regexec匹配大家的靶子文本串了,如若在编译正则表明式的时候从不点名cflags的参数为REG_NEWLINE,则默许情形下是忽视换行符的,也等于把全部文本串当作二个字符串处理。

      • 施行成功重返0。
      • regmatch_t是二个结构体数据类型,在regex.h中定义:

        typedef struct {
            regoff_t rm_so;
            regoff_t rm_eo;
        } regmatch_t;
        
      • 成员rm_so存放匹配文本串在目的串中的初始地点,rm_eo存放停止地点。经常大家以数组的款式定义一组那样的构造。因为反复大家的正则表明式中还包含子正则表达式。数组0单元存放主正则表达式地方,前边的单元依次存放正则表明式地方。

      • int regexec(regex_t *compiled, char *string, size_t nmatch, regmatch_t matchptr[], int eflags)
        • compiled:是已经用regcomp函数编译好的正则表达式。
        • string:是目的文本串。
        • nmatch:是regmatch_t结构体数组的尺寸。
        • matchptr:regmatch_t类型的结构体数组,存放匹配文本串的地点音信。
        • eflags有三个值:
          • REG_NOTBOL:让特殊字符^无效益。
          • REG_NOTEOL:让特殊字符$无听从。
    • 叁,当大家使用完编译好的正则表明式后,可能要重新编译其他正则表明式的时候,大家可以用那么些函数清空compiled指向的regex_t结构体的内容,请记住,借使是重复编译的话,一定要先清空regex_t结构体。

      • void regfree(regex_t *compiled)
    • 四,当执行regcomp大概regexec暴发错误的时候,就足以调用这么些函数而回到三个富含错误新闻的字符串。
      • size_t regerror(int errcode, regex_t *compiled, char *buffer, size_t length)
        • errcode:是由regcomp和regexec函数重临的谬误代号。
        • compiled:是现已用regcomp函数编译好的正则表明式,那一个值可以为NULL。
        • buffer:指向用来存放错误消息的字符串的内存空间。
        • length:指明buffer的长度,倘诺那一个错误消息的尺寸超越这么些值,则regerror函数会自行截断超出的字符串,但他如故会回到完整的字符串的长度。所以我们可以用如下的点子先得到错误字符串的长短。
        • 例如:size_t length = regerror(errcode, compiled, NULL, 0);
    • 测试用例:

      #include <sys/types.h>
      #include <regex.h>
      #include <stdio.h>
      
      int main(int argc, char *argv[])
      {
          if(argc != 3){ 
              printf("Usage: %s RegexString And Text\n", argv[0]);
          }   
      
          const char * p_regex_str = argv[1];
          const char * p_txt = argv[2];
          //编译后的结构体
          regex_t oregex;
          int ret = 0;
          //保存错误信息的数组
          char emsg[1024] = {0};
          size_t emsg_len = 0;
      
          //编译正则表达式, 扩展正则
          if((ret = regcomp(&oregex, p_regex_str, REG_EXTENDED|REG_NOSUB)) == 0){ 
              //执行匹配,不保存匹配的返回值
              if((ret = regexec(&oregex, p_txt, 0, NULL, 0)) == 0){ 
                  printf("%s matches %s\n", p_txt, p_regex_str);
                  regfree(&oregex);
                  return 0;
              }   
          }   
      
          //正则编译错误,存emsg中错误描述
          emsg_len = regerror(ret, &oregex, emsg, sizeof(emsg));
          //错误信息较长特殊情况
          emsg_len = emsg_len < sizeof(emsg)? emsg_len : sizeof(emsg) - 1;
      
          emsg[emsg_len] = '\0';
          printf("Regex error Msg: %s\n", emsg);
      
          regfree(&oregex);
      
          //非正常退出                                                                                             
          return 1;
      }
      
    • 匹配网址:

      ./a.out "http:\/\/www\..*\.com" "http://www.taobao.com"
      
    • 合作邮箱:

      ./a.out "^[a-zA-Z0-9.]+@[a-zA-Z0-9]+.[a-zA-Z0-9]+" "abc.123@126.com"
      ./a.out "\w+([-+.]\w+)*@\w+([-+.]\w+)*\.\w+([-+.]\w+)*" "abc@qq.com"
      
    • 匹配固话号码:请同学们融洽编写。

    • 除去GNU提供的函数外,还常用PCRE处理正则,全称是Rerl Compatible
      Regular
      Expressions。从名字我们可以看到PCRE库是与Perl中正则表明式相协作的3个正则表达式库。PCRE是免费开源的库,它是由C语言完毕的,那里是它的官方主页:http://www.pcre.org/,感兴趣的情侣可以在那边明白更加多的始末。要拿走PCRE库,可以从此处下载:http://sourceforge.net/projects/pcre/files/
    • PCRE++是一个对PCRE库的C++封装,它提供了越发便于、易用的C++接口。那里是它的官方主页:

awk

  • sed以行为单位处理公事,awk比sed强的地点在于不仅能以行为单位仍是可以以列为单位拍卖文件。awk缺省的行分隔符是换行,缺省的列分隔符是连接的空格和Tab,但是行分隔和列分隔符都得以自定义,比如/etc/passwd文件的每一行有几多个字段,字段之间以:分隔,就足以再次定义awk的列分隔符为:并以列为单位拍卖这几个文件。awk实际上是一门很复杂的脚本语言,还有像C语言一样的道岔和巡回结构,但是基本用法和sed类似,awk命令行的着力形式为:

    awk option 'script' file1 file2 ...
    awk option -f scriptfile file1 file2 ...
    
  • 和sed一样,awk处理的文书既能够由标准输入重定向得到,也得以当命令行参数传入,编辑命令可以平昔当命令行参数传入,也可以用-f参数指定1个本子文件,编辑命令的格式为:

    /pattern/{actions}
    condition{actions}
    
  • 和sed类似,pattern是正则表明式,actions是一比比皆是操作。awk程序一行一行读出待处理公事,假如某一行与pattern匹配,或许满足condition条件,则实施相应的actions,假设一条awk命令只有actions部分,则actions成效于待处理文件的每一行。比如文件testfile的故事情节表示某商厦的库存量:

    ProductionA 30
    ProductionB 76      
    ProductionC 55
    
  • 打印每一行的第二列:

    $ awk '{print $2;}' testfile
    30
    76
    55
    
  • 电动变量$壹,$2各自代表第一列、第二列等,类似于Shell脚本的岗位参数,而$0表示所有当前行。再比如说,倘使某种产品的库存量低于75则在末行标注须要预定:

    $ awk '$2<75 {printf "%s\t%s\n", $0, "REORDER";} $2>=75 {print $0;}' testfile
    ProductionA 30 REORDER
    ProductionB 76      
    ProductionC 55 REORDER
    
  • 可知awk也有和C语言非凡相像的printf函数。awk命令的condition部分还可以够是多少个尤其的condition——BEGIN和END,对于逐个待处理文件,BEGIN后边的actions在拍卖整个文件此前实施五回,END前面的actions在全方位文件处理完之后执行四遍。

  • awk命令可以像C语言一样使用变量(但不须求定义变量),比如计算1个文本中的空行数

    $ awk '/^ *$/ {x=x+1;} END {print x;}' testfile
    
  • 似乎Shell的环境变量一样,某个awk变量是预订义的有破例含义的:

    • awk常用的内建变量

      FILENAME    当前输入文件的文件名,该变量是只读的
      NR          当前行的行号,该变量是只读的,R代表record
      NF          当前行所拥有的列数,该变量是只读的,F代表field
      OFS         输出格式的列分隔符,缺省是空格
      FS          输入文件的列分隔符,缺省是连续的空格和Tab
      ORS         输出格式的行分隔符,缺省是换行符
      RS          输入文件的行分隔符,缺省是换行符
      
  • 例如打印系统中的用户帐号列表

    $ awk 'BEGIN {FS=":"} {print $1;}' /etc/passwd
    
  • awk也可以像C语言一样采取if/else、while、for控制结构。可自动扩张学习。

C程序中采纳正则

  • POSIX规定了正则表达式的C语言库函数,详见regex(3)。我们曾经学习了不少C语言库函数的用法,读者应当享有本人看懂man手册的力量了。本章介绍了正则表明式在grep、sed、awk中的用法,学习要能够触类旁通,请读者依照regex(3)自身计算正则表明式在C语言中的用法,写一些签单的次序,例如验证用户输入的IP地址或email地址格式是还是不是正确。
  • C语言处理正则表明式常用的函数有regcomp()、regexec()、regfree()、regerror(),一般分为七个步骤,如下所示:
    • 1、编译正则表达式regcomp()
    • 2、匹配正则表明式regexec()
    • 三,释放正则表达式regfree()
  • 上面是对两个函数的详细解释

    • 壹,regcomp()那些函数把指定的正则表明式pattern编译成一种特定的数目格式compiled,那样可以使非常更使得。函数regexec会利用那些数据在目的文本串中开展情势匹配。执行成功重临0。
      • int regcomp(regex_t *compiled, const char *pattern, int cflags)
      • regex_t:是3个结构休数据类型,用来存放在编译后的正则表达式,它的成员re_nsub用来储存正则表明式中的子正则表明式的个数,子正则表明式就是用圆括号包起来的一部分表达式。
      • pattern:是指向大家写好的正则表达式的指针。
      • cflags有如下六个值可能是它们或运算(|)后的值:
        • REG_EXTENDED:以职能越来越强硬的壮大正则表达式的主意进行匹配。
        • REG_ICASE:匹配字母时忽略大小写
        • REG_NOSUB:不用存储匹配后的结果,只回去是不是中标匹配。借使设置该标志位,那么在regexec将忽略nmatch和pmatch五个参数。
        • REG_NEWLINE:识别换行符,那样’$’就可以从行尾初步匹配,’^’就可以从行的开关开始匹配。
    • 二,当大家编译好正则表达式后,就足以用regexec匹配大家的目标文本串了,即使在编译正则表明式的时候没有点名cflags的参数为REG_NEWLINE,则暗中认可意况下是忽视换行符的,约等于把整个文本串当作二个字符串处理。

      • 实施成功重回0。
      • regmatch_t是3个结构体数据类型,在regex.h中定义:

        typedef struct {
            regoff_t rm_so;
            regoff_t rm_eo;
        } regmatch_t;
        
      • 成员rmso存放匹配文本串在对象串中的起首地点,rmeo存放截止地方。平日大家以数组的样式定义一组那样的构造。因为屡次大家的正则表达式中还包涵子正则表明式。数组0单元存放主正则表明式地方,前边的单元依次存放正则表明式地方。

      • int regexec(regex_t *compiled, char *string, size_t nmatch, regmatch_t matchptr[], int eflags)

        • compiled:是已经用regcomp函数编译好的正则表达式。
        • string:是目的文本串。
        • nmatch:是regmatch_t结构体数组的尺寸。
        • matchptr:regmatch_t类型的结构体数组,存放匹配文本串的地方音讯。
        • eflags有五个值:
          • REG_NOTBOL:让杰出字符^无效果。
          • REG_NOTEOL:让卓越字符$无意义。
    • 三,当大家运用完编译好的正则表明式后,可能要双重编译其余正则表明式的时候,大家可以用那么些函数清空compiled指向的regext结构体的内容,请记住,即便是重复编译的话,一定要先清空regext结构体。

      • void regfree(regex_t *compiled)
    • 肆,当执行regcomp或许regexec发生错误的时候,就足以调用这几个函数而回到3个饱含错误消息的字符串。

      • size_t regerror(int errcode, regex_t *compiled, char *buffer, size_t length)
        • errcode:是由regcomp和regexec函数再次来到的不当代号。
        • compiled:是早就用regcomp函数编译好的正则表明式,那个值可以为NULL。
        • buffer:指向用来存放错误新闻的字符串的内存空间。
        • length:指明buffer的尺寸,假诺这些错误新闻的长短当先那些值,则regerror函数会自动截断超出的字符串,但她一如既往会回来完整的字符串的尺寸。所以我们得以用如下的方法先拿到错误字符串的长度。
        • 例如:size_t length = regerror(errcode, compiled, NULL, 0);
    • 测试用例:

      #include <sys/types.h>
      #include <regex.h>
      #include <stdio.h>
      
      int main(int argc, char *argv[])
      {
          if(argc != 3){ 
              printf("Usage: %s RegexString And Text\n", argv[0]);
          }   
      
          const char * p_regex_str = argv[1];
          const char * p_txt = argv[2];
          //编译后的结构体
          regex_t oregex;
          int ret = 0;
          //保存错误信息的数组
          char emsg[1024] = {0};
          size_t emsg_len = 0;
      
          //编译正则表达式, 扩展正则
          if((ret = regcomp(&oregex, p_regex_str, REG_EXTENDED|REG_NOSUB)) == 0){ 
              //执行匹配,不保存匹配的返回值
              if((ret = regexec(&oregex, p_txt, 0, NULL, 0)) == 0){ 
                  printf("%s matches %s\n", p_txt, p_regex_str);
                  regfree(&oregex);
                  return 0;
              }   
          }   
      
          //正则编译错误,存emsg中错误描述
          emsg_len = regerror(ret, &oregex, emsg, sizeof(emsg));
          //错误信息较长特殊情况
          emsg_len = emsg_len < sizeof(emsg)? emsg_len : sizeof(emsg) - 1;
      
          emsg[emsg_len] = '\0';
          printf("Regex error Msg: %s\n", emsg);
      
          regfree(&oregex);
      
          //非正常退出                                                                                             
          return 1;
      }
      
    • 匹配网址:

      ./a.out "http:\/\/www\..*\.com" "http://www.taobao.com"
      
    • 格外邮箱:

      ./a.out "^[a-zA-Z0-9.][email protected][a-zA-Z0-9]+.[a-zA-Z0-9]+" "[email protected]"
      ./a.out "\w+([-+.]\w+)*@\w+([-+.]\w+)*\.\w+([-+.]\w+)*" "[email protected]"
      
    • 匹配固话号码:请同学们团结编写。

    • 除却GNU提供的函数外,还常用PCRE处理正则,全称是Rerl Compatible
      Regular
      Expressions。从名字大家可以见到PCRE库是与Perl中正则表明式相包容的三个正则表明式库。PCRE是免费开源的库,它是由C语言完结的,那里是它的官方主页:

    • PCRE++是2个对PCRE库的C++封装,它提供了更进一步有利、易用的C++接口。那里是它的官方主页:

Shell历史
Shell的功能是表达用户的吩咐,用户输入一条命令,Shell就分解施行一条,那条办法叫做交互式(interactive),…

相关文章