码迷,mamicode.com
首页 > 编程语言 > 详细

20150915 Linux 数组 sed awk

时间:2015-09-28 19:11:28      阅读:243      评论:0      收藏:0      [点我收藏+]

标签:linux   空间   color   元素   命名   

第一部分数组:

bash脚本编程:
    变量:变量名   ,命名的命名空间
    数组:连续的多个独立内存空间;每个内存空间相当于一个变量;
        数据元素的引用:数组名[索引]

    bash 4.0+以后版本支持二种类型:
        传统数组(基本数组):索引为数字,从0开始编号;
            declare -a ARRAY_NAME
        关联数组:索引可以自定义,可以使用任意字符串做索引;
            declare -A ARRAY_NAME

        支持稀疏格式(指赋值第一个后,可随意跳到第3个或4、7等,可不连续)

    数组元素的赋值方式:
        (1) 一次只赋值一个元素
            array[index]=value
        (2) 一次赋值全部元素
            array=("val1" "val2" ...)   #从索引0,1,2….开始,顺序的
        (3) 指定索引进行赋值
            array=([0]="val1" [3]="val2")   #区别指名索引,稀疏格式
        (4) read -a array  #基于,多个一个元素在一个数组中

      示例:将变量tom ,jerry,ben保存在一数组arrary当中,利用array数组

下面加索引的方式。进行调用

     技术分享

    引用元素:${array[index]}

    长度(数组的长度):${#array[*]}, ${#array[@]}

    练习:利用bash生成10个随机数值,保存于数组中;要此些数组排序
        $RANDOM (从0至32767) 示例:echo $RANDOM(注意必须是大写)

 技术分享技术分享

 

第二部分:Sed命令
    
    grep, sed, awk
        grep: 文本搜索工具;egrep, fgrep
        sed: stream editor, 流编辑器;
        awk(gawk):文本格式化工具,报告生成器

第一:sed运行方式

        sed一次读取一行。可以是指定范围的行,或者表达式。

一次读一行后运行在自己的模式空间(pattern space),针对文本进行

处理。判断是否符合判断条件进行编辑操作,符合条件处理后输出

到屏幕当中。即打印模式空间(默认)不管是否成功。

技术分享

第二:sed命令:

1) 基本正则表达式元字符:
            字符匹配:., [], [^]
            次数匹配:*, \?, \+, \{m,n\}, \{n\}
            位置锚定:^, $, \<, \>
            分组及引用:\(\), \1, \2, ...
            多选一:a|b|c

        vim编辑中文本的查找替换:
            地址定界s/要查找的内容/替换为的内容/
                要查找的内容:可使用正则表达式
                替换为的内容:不支持正则表达式,但支持引用前面正则表达式分组中的内容
                地址定界:%, startline,endline

  2)语法      

语法:sed [OPTION]... {script} [input-file]...

工作机制:每次读取一行文本至“模式空间(pattern space)”中,在模式空间中完成处理;将处理结果输出至标准输出设备;

  A) Option选项

          -r: 支持扩展正则表达式; 
          -n: 静默模式; (指只打印静默默认的行,没有要求输出不做输出操作) 
          -e script1 -e script2 -e script3:指定多脚本运行; 
          -f /path/to/script_file:从指定的文件中读取脚本并运行; 
          -i: 直接修改源文件;(默认sed不会对源文件作操作)

  B)脚本

   其中脚本包括地址定界和编辑命令二个功能

     地址定界: (类型VIM) 
       #: 指定行;  :#  指定行 
       $: 最后一行; 
      /regexp/:任何能够被regexp所匹配到的行; 
      \%regexp%:同上,只不过换作%为regexp边界符; 
      /regexp/| : 
      \%regexp%| :匹配时忽略字符大小写; 
      startline,endline: 
          #,/regexp/:从#行开始,到第一次被/regexp/所匹配到的行结束,中间的所有行; 
          #,#  

示例:sed ‘1,4d’ /etc/fstab 删除1至4行

技术分享 
   /regexp1/,/regexp2/:从第一次被/regexp1/匹配到的行开始,到第一次被/regexp2/匹配到的行结束,中间的所有行; 
      #,+n:从#行开始,一直到向下的n行; 
  first~step:指定起始行,以及步长; 
       1~2,  说明从1开始,步进为2,这样为1,3,5,7.。。。奇数行

       2~2 ,说明 从2开始,步进为2,这样为2,3,4,6,8 。。。偶数行

sed的编辑命令 
          d: 删除模式空间中的行;

示例:不显示/etc/fstab中以UUID开始的行

技术分享 
=:显示行号; (不在同一行)

示例 sed ‘1,4=’ /etc/fstab

技术分享 
a \text:附加text

示例  sed ‘/^UUID/a \newline‘ /etc/fstab  同时也可以转意再添加一行

  sed ‘/^UUID/a \newline \n secondline‘ /etc/fstab

技术分享

技术分享

i \text:插入text,支持\n实现多行插入; (在符合条件行之前)

技术分享

  c \text:用text替换匹配到的行;
技术分享

p: 打印模式空间中的行; (默认情况下,sed会打印模式空间的行,当

满足条件时会打印二行)

技术分享

  针对静默空间的行采用-n选项

技术分享

s/regexp/replacement/:替换由regexp所匹配到的内容为replacement; 
       g: 全局替换;

技术分享 
              
w /path/to/somefile:把指定的内容另存至/path/to/somefile路径所指定的文件中;

示例:将奇数行保存至/tmp/fstab.odd文件当中

技术分享

  r /path/from/somefile:在文件的指定位置插入另一个文件的所有内容,完成文件合并;

示例:将/etc/issue文件中插入到第五行后,完成文件合并

技术分享

练习: 
(1) 删除/boot/grub/grub.conf文件中所有行的行首的空白字符; 
   sed ‘s/^[[:space:]]\+//‘ /boot/grub/grub.conf    #//替换为空  全文件查找不用使用定界

          可在s前填加地址定界,例如第10行。。。

技术分享

       删除空白行

    sed ‘/^$/d’ /etc/grub2.cfg 
(2) 删除/etc/fstab文件中所有以#开头,后跟至少一个空白字符的行的行首的#和空白字符; 
    sed ‘s/^#[[:space:]]\+//‘ /etc/fstab    #\+匹配次数1 
(3) 把/etc/fstab文件的奇数行另存为/tmp/fstab.3; 
        sed ‘1~2w /tmp/fstab.3‘ /etc/fstab 
(4) echo一个文件路径给sed命令,取出其基名;进一步地,取出其路径名; 
      取基名:echo "/etc/sysconfig/network-scripts/" | sed ‘s@^.*/\([^/]\+\)/\?$@\1@‘ 
     取路径名:echo "/etc/sysconfig/network-scripts/" | sed ‘s@[^/]\+/\?$@@‘

 

sed命令另一个称作"hold space"的内存空间:保持空间

技术分享

    pattern space这加工厂,hold space为仓库。用的时候还可以取回。

只能够在pattern space编辑。

      高级命令: 
        h:用模式空间中的内容覆盖保持空间的内容; 
        H:把模式空间中的内容追加至保持空间中内容的后面; 
        g:从保持空间中取到其内容,并将其覆盖模式空间中的内容; 
        G:从保持空间中取到其内容,并将其追加在模式空间中的内容的后面; 
        x:把保持空间和模式空间中的进行交换; 
       n:读取匹配到的行的下一行至模式空间;(会覆盖模式空间中的原有内容); 
       N:读取匹配到的行的下一行至模式空间,追加在模式空间中原有内容的后面; 
       d:删除模式空间中的内容; 
       D:删除多行模式空间中的首行;

注意:命令功能可使用!取反(针对地址取反);分号可用于分隔脚本;

示例:

sed ‘1,3!d‘ /etc/fstab   表示1至3行之外行删除掉,这里针对地址定界取反

技术分享
sed ‘G‘ /etc/issue: 在文件中的每行后方添加空白行; 因为模式空间为空 
技术分享

sed ‘$!d‘ /etc/fstab:保留最后一行;   $表示最后一行

技术分享
sed ‘/^$/d;G‘ /etc/issue: 保证指定的文件每一行后方有且只有一个空白行;

  (如果前为空白行删除,非空白行后面添加一个空白行)

  ^$为空白行  
  sed ‘n;d‘ /etc/issue:保留奇数行; 从外命令分号分隔开(每读的下一行为偶数行)

当读1行第时,这时第2行会删除以此类推)

技术分享

  sed -n ‘1!G;h;$p‘ /etc/issue   $p打印最后一行,第一行不做get,不从

保存空间取内容。示例:左侧第一排为输入文件,中间一排为模式空间,第三排

为保存空间。输出为4,3,2,1;功能:逆序显示文件内容

-n没有要求输出,不做输出操作

tac 命令用于逆向显示

技术分享


    sed ‘$!N;$!D‘ /etc/issue  显示最后一行

  技术分享

    sed命令:
            -e ‘script‘ -e ‘script‘
            ‘script;script;script‘

            script
            script
            script

            -f /path/from/script

第三部分:AWK

1)定义及工作方式

  AA:定义

      首先awk为c语言风格

awk:
    grep, sed, awk (文件格式化输出工具)
        grep: 文本过滤器
        sed: 行编辑器
        awk: 报告生成器(早期在Unix版本)

    AWK a.k.a Aho, Weinberger, Kernighan

    Gnu AWK, gawk(awk是指向gawk的链接)

    ls –l `which awk`

技术分享

   awk功能相比sed更加强大支持if语句、条件判断、数组、自定义函数等功能

BB:工作模式

     一次读一行到自己的命名空间,不对每行做操作只针对符合条件的行进行编辑,

进行地址定界。在awk里面称为模式。

    将一行文本信息,按照用户指定的格式或分隔符切成n片。保存到awk指定的

变量当中。引用整行用$0,引用某段利用$1,$2。。。进行引用

 技术分享

  2)基本语法
    awk [options] ‘program‘ file file ...
    awk [options] ‘PATTERN{action}‘ file file ...

awk的类似cut,每个 program可分解为pattern{action}

内置一次读一行(循环处理每一行之意),其中action常用

的包括print(简单输出)、printf(格式化输出)

示例: 显示/etc/passwd以冒号分隔的第一段

awk -F: ‘{print $1}‘ /etc/passwd

 技术分享

    -F CHAR:输入分隔符   ‘{ }’ 表示引用自己的脚本,$1第一字段

加$表示引用字段

    A、awk的输出

    print item1, item2,...

    itme1、item2可为字符、也可以为字符串(必须双引号)
    要点:
    (1) 各项目之间使用逗号分隔,而输出时则使用输出分隔符分隔;

各项目之间输出以空格分隔,逗号有多个条之意

技术分享

     如果$1,$3之间为空后,将二个项目相联

技术分享
    (2) 输出的各item可以字符串或数值、当前记录的字段、变量或awk的表达式;

数值会被隐式转换为字符串后输出;
    (3) print后面item如果省略,相当于print $0;输出空白,使用pirnt "";

技术分享

    B、awk的变量
        内置变量,自定义变量,注意内部引用变量不需要$

    2.1 内置变量 (awk自带的)
    FS:Field Seperator, 输入时的字段分隔符
        # awk ‘BEGIN{FS=":"}{print $1,$7}‘ /etc/passwd

    RS:Record Seperator, 输入行分隔符
    OFS: Output Field Seperator, 输出时的字段分隔符;
    ORS: Outpput Row Seperator, 输出时的行分隔符;

    NF:Numbers of Field,每一行的字段数 :默认以空格进行统计。无空格为1

技术分享
    NR:Numbers of Record, 行数/号;所有文件的一并计数; 进行行统计

示例:awk ` (printf NR,$0)’ /etc/fstab /etc/issue

技术分享

      如果NR前加$NR表示读取字段数的值(原文件左侧

awk ‘{print $NF}‘ /etc/grub2.cfg  以最后一段为4(该语句含义打印第四4个字段,

如果是其它字段则变化,实际为打印最后一个字段的值)

技术分享技术分享

    FNR:行数;各文件分别计数;
技术分享

    ARGV:数组,保存命令本身这个字符,awk ‘{print $0}‘ 1.txt 2.txt,意味着ARGV[0]保存awk,
    ARGC: 保存awk命令中参数的个数;
    FILENAME: awk正在处理的当前文件的名称;

    2.2 可自定义变量
        -v var_name=VALUE    -v表示给一个变量赋值

        变量名区分字符大小写;

        (1) 可以program中定义变量;
        (2) 可以命令行中通过-v选项自定义变量;

示例:定义变量test,在打印时引用变量,加到输入字段输出

技术分享

  示例:打印每个及最后一个字段(冒号分隔)

技术分享

   awk -F: ‘{print $1,$NF}‘ /etc/passwd   命令可修改为

   awk -v FS=: ‘{print $1,$NF}‘ /etc/passwd   其中FS为变量,同时

FS为内置输入时的分隔符。这里为:(冒号)

技术分享

  # awk -v FS=: -v OFS=# ‘{print $1,$NF}‘ /etc/passwd

使用OFS为输出时的分隔符,这样字段1和最后一个字段时间以#号分隔

    3、awk的printf命令(f代表format ,可定义相应的格式)

        命令的使用格式:printf format, item1, item2,...

每个itme都会对应相应的format

        要点:
        (1) 要指定format;
        (2) 不会自动换行;如需换行则需要给出\n
        (3) format用于为后面的每个item指定其输出格式;

        format格式的指示符都%开头,后跟一个字符:
            %c: 显示字符的ASCII码;
            %d, %i: 十进制整数;
            %e, %E: 科学计数法显示数值;
            %f: 显示浮点数;
            %g, %G: 以科学计数法格式或浮点数格式显示数值;
            %s: 显示字符串;
            %u: 显示无符号整数;
            %%: 显示%自身;

        修饰符:
            #:显示宽度  3代表三个字符的宽度
            -:左对齐
            +:显示数值的符号
            .#: 取值精度

示例:

awk -F: ‘{printf "UID:%d\n",$3}‘ /etc/passwd

以UID:xxxx;显示%d表示十进制数,\n表示换行,将$3放到

format中进行显示

技术分享

  将修饰符添加到%d前端例如 %10d表示宽度为10,%.10d表示

10个字符,前会以0补充。(默认靠右对齐如%-10d 左对齐)

技术分享

技术分享

    4、awk输出重定向 (未讲解)
        print items > output-file
        print items >> output-file
        print items | command

示例:将输出保存到/tmp/51cto/awkout文件中

技术分享

        特殊文件描述符:
        /dev/stdin: 标准输入
        /dev/stdout: 标准输出
        /dev/stderr: 错误输出

    5、awk的操作符

        算术操作符:
            x+y
            x-y
            x*y
            x/y
            x**y, x^y    求次方
            x%y   取模
             -x:负值
            +x:转换为数值

        字符串操作符:连接  不需要任何,不能够使用逗号,

        赋值操作符:
            =
            +=
            -=
            *=
            /=
            %=
            ^=
            **=

            ++     自加
             --      自减

            如果模式自身是=号,要写为/=/

        比较操作符:
            <
            <=
            >
            >=
            ==
            !=
            ~:模式匹配,左边的字符串能够被右边的模式所匹配为真,否则为假;
            !~:

        逻辑操作符:
            &&: 与
            ||:或

        条件表达式: (双分支语句)
        selector?if-true-expression:if-false-expression

   selector是个挑选器,如果真执行if-true-express分支,假执行if-false分支

示例: 

# awk -F: ‘{$3>=1000?utype="common user":utype="admin or system user";print $1,"is",utype}‘

/etc/passwd

        函数调用: (支持内部或外部函数)
        function_name(argu1,argu2)  #以函数名加用户参数的形式指定。

 

  后续进行awk的pattern和Action

6、模式

   awk pattern支持的五种类型

  (1) Regexp: 格式为/PATTERN/    模式匹配到的行进行处理,否则不进行处理 
      仅处理被/PATTERN/匹配到的行;

示例 awk ‘{print $3}‘ /etc/fstab 

技术分享

   以UUID开始的行

技术分享 
  (2) Expression: 表达式,其结果为非0或非空字符串时满足条件; 
      仅处理满足条件的行; (利用比较操作符)

示例:awk -F: ‘$3>=1000 {print $1,$3}‘ /etc/passwd

技术分享

awk -F: ‘$NF~/bash$/ {print $1,$NF} ‘ /etc/passwd

   $NF表示结尾 $NF代表最后一个字段

      ~:模式匹配,左边的字符串能够被右边的模式所匹配为真,否则为假; 
      !~

     bash$表示以bash结尾

技术分享

awk -F: ‘$NF!~/bash$/ {print $NF} ‘ /etc/passwd   最后字段非bash结尾

技术分享

  (3) Ranges: 行范围,此前地址定界,  

        NR   行号 
       仅处理范围内的行

awk -F: ‘NR>=15 && NR<=20 {print $1,$NF}‘ /etc/passwd  输出15至20行的内容

技术分享 
(4) BEGIN/END: 特殊模式,

仅在awk命令的program运行之前(BEGIN)或运行之后(END)执行一次;

示例:在运行之后打印一行”=====usernme====shell====”

技术分享

Begin和End之间或之后使用相应变量,或提示信息等 
(5) Empty:空模式,匹配任意行;(如果未指定行说明是所有行)

技术分享

7、常用的action

    (1) Expressions    表达式 :比较、算术代表式等,多个用分号分隔 
    (2) Control statements        控制语句 
    (3) Compound statements   组合语句 
    (4) input statements   输入语句 
   (5) output statements  输出语句  print   printf

8、控制语句

    8.1 if-else 
      格式:if (condition) {then body} else {else body}  注意:条件是小括号

  # awk -F: ‘{if ($3>=500) {print $1,"is a common user"} else {print $1, "is an admin or system user"}}‘ /etc/passwd  
     针对以下针对centos 6如果是7 id大于1000

   # awk ‘{if (NF>=8) {print}}‘ /etc/inittab   :当字段数大于打印整行内容  NF字段数,无else直接 print(单分支)

       NR行号

#  awk ‘{if (NF>=8) {print $0} else {print NR,$0}}‘ /etc/inittab    #大于8显示行号,不大于8不显示行号

技术分享

   判断用户id与组id是否一致

  # awk -F: ‘{if ($3==$4) {print $1, "good user"}}‘ /etc/passwd

技术分享

  8.2 while (一般用于针对某字段做类似处理) 
      格式:while (condition) {while body}    条件为真执行

    # awk ‘{i=1; while (i<=NF){printf "%s ",$i;i+=2};print ""}‘ /etc/inittab  

           显示奇数字段,print能够换行 
  # awk ‘{i=1; while (i<=NF){if (length($i)>=6) {print $i}; i++}}‘ /etc/inittab

         字段串长度大于6显示

   length()函数:取字符串的长度

      %s: 显示字符串;

8.3 do-while循环

    至少执行一次,不管条件是否为真或假 
     格式:do {do-while body} while (condition) 

8.4 for循环 
     格式:for (variable assignment; condition; iteration process) {for body} 
# awk ‘{for (i=1;i<=NF;i+=2){printf "%s ",$i};print ""}‘ /etc/inittab  显示奇数字段 
# awk ‘{for (i=1;i<=NF;i++){if (length($i)>=6) print $i}}‘ /etc/inittab

   for循环可用来遍历数组元素: 
         语法:for (i in array) {for body}

8.5 case语句 
  语法:switch (expression) {case VALUE or /RGEEXP/: statement1;... default: stementN}

      都不满足执行default语句

8.6 循环控制 
      break   提前终止循环 
      continue    提前终止本轮循环   针对字段

8.7 next 【针对行】 
      提前结束对本行的处理进而提前进入下一行的处理; 
       # awk -F: ‘{if($3%2==0) next;print $1,$3}‘ /etc/passwd   #显示奇数用户的id 
       # awk -F: ‘{if(NR%2==0) next; print NR,$1}‘ /etc/passwd

9、数组

     传统数组:Index编号从1开始; 
     关联数组:

       array[index-expression]

       index-expression: 可以使用任意字符串; 如果某数组元素事先不存在,那么在引用时,

awk会自动创建此元素并将其初始化为空串;因此,要判断某数组是否存在某元素,

必须使用“index in array”这种格式;

                A[first]="hello awk"
                print A[second]

     要遍历数组中的每一个元素,需要使用如下特殊结构: 
        for (var in array) {for body}  #var保存的是array的每一个索引

            其var会遍历array的索引;

示例: 如附字符串时需要在数组中以双引号 test[“ 字符串”]

技术分享

利用for循环语句输出

# awk ‘BEGIN{test["mon"]="monday";test["tue"]="tuesday";for (i in test){print test[i]}}‘

技术分享

        state[LISTEN]++ 
       state[ESTABLISHED]++

      NF字段数;$NF最后一个字段

# netstat -tan | awk ‘/^tcp/{++state[$NF]}END{for (s in state) {print s,state[s]}}‘

显示链接的个数,^tcp协议类型,state数组,将状态保存到数组当中,当有一个元素时

加1用++表示,awk自动循环。这里数组state当中包括二种listen的数量和establised数量。

最后用end在最后面一次输出相应的值

技术分享

# awk ‘{ip[$1]++}END{for (i in ip) {print i,ip[i]}}‘ /var/log/httpd/access_log

统计每个IP地址请求次数,需要利用httpd服务

AA:启动httpd服务的80端口

技术分享

BB:编辑 vim /var/www/html/index.html, 随意输入内容

技术分享

CC:运行 ab -n 10000 -c 100 http://192.168.6.184/index.html 模拟请求

ab为apache测试工具

技术分享

DD:查看/var/log/httpd/access_log目录内容

   显示客户端对服务端 的请求

技术分享

EE:利用输出语句,汇总相关信息

   统计每个IP地址请求次数

技术分享

 

删除数组元素: 
       delete array[index]

10、awk的内置函数

split(string,array[,fieldsep[,seps]]): 
        功能:将string表示的字符串以fieldsep为分隔符进行切片,

并切片后的结果保存至array为名的数组中;数组下标从1开始;

     root:x:0:0::/root:/bin/bash

     user[1]="root", user[2]

       此函数有返回值,返回值为切片后的元素的个数

# netstat -tn | awk ‘/^tcp/{lens=split($5,client,":");ip[client[1]]++}END{for (i in ip) print i,ip[i]}‘

显示第五个这段冒号前的地址,保存到数组client当中进行统计

技术分享      

length(string) 
      功能:返回给定字串的长度

substr(string,start[,length]) 
       功能:从string中取子串,从start为起始位置为取length长度的子串;

    博客:sed和awk的使用

20150915 Linux 数组 sed awk

标签:linux   空间   color   元素   命名   

原文地址:http://wangsongbin.blog.51cto.com/1130001/1698880

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!