sed & awk

正則表達式

sed: stream editor, 流編輯器;
awk(gawk):文本格式化工具,報告生成器express

 

二 sed         stream editor for filtering and transforming textvim

sed [OPTION]... {script-only-if-no-other-script} [input-file]...數組

工做機制:每次讀取一行文本至「模式空間(pattern space)」中,在模式空間中完成處理;將處理結果輸出至標準輸出設備;bash

sed 不加-i參數,不會修改源文件,只會顯示修改後的內容在輸出設備app

 

命令參數tcp

-r                                                支持擴展正則表達式;
-n                                               靜默模式;
-e script1 -e script2 -e script3   指定多腳本運行;
-f /path/to/script_file                從指定的文件中讀取腳本並運行;
-i                                                直接修改源文件;編輯器

 

基本正則表達式元字符:
字符匹配:., [], [^]
次數匹配:*, \?, \+, \{m,n\}, \{n\}
位置錨定:^, $, \<, \>
分組及引用:\(\), \1, \2, ...
多選一:a|b|cide

 

地址定界:
  #                          指定行
  $                          最後一行
  /regexp/              任何可以被regexp所匹配到的行
  \%regexp%          同上,只不過換做%爲regexp邊界符
  /regexp/|             匹配時忽略字符大小寫
  \%regexp%|         匹配時忽略字符大小寫,只不過換做%爲regexp邊界符函數

  startline,endline:
      #,/regexp/                      從#行開始,到第一次被/regexp/所匹配到的行結束,中間的全部行;
      #,#
      /regexp1/,/regexp2/      從第一次被/regexp1/匹配到的行開始,到第一次被/regexp2/匹配到的行結束,中間的全部行;
      #,+n                                從#行開始,一直到向下的n行;
  first~step                            指定起始行,以及步長;      1~2,2~2

 

sed的編輯命令
 d                                            刪除模式空間中的行
 =                                            顯示行號
 a \text                                    附加text
 i \text                                     插入text,支持\n實現多行插入
 c \text                                    用text替換匹配到的行
 p                                            打印模式空間中的行
 s/regexp/replacement/         替換由regexp所匹配到的內容爲replacement
 g                                            全局替換
   
 w /path/to/somefile              把指定的內容另存至/path/to/somefile路徑所指定的文件中
 r /path/from/somefile           在文件的指定位置插入另外一個文件的全部內容,完成文件合併

 

[root@localhost ~]# echo Sunday | sed 's/day/night/'       #替換Sunday中的day爲night
Sunnight
[root@localhost test]# vim xxx.txt 
1
2
3
4
5

刪除

[root@localhost test]# sed "1d" xxx.txt     #刪除第一行
2
3
4
5
[root@localhost test]# sed "$d" xxx.txt     #刪除最後一行                   
1
2
3
4
5
[root@localhost test]# sed '$d' xxx.txt      #刪除最後一行                  
1
2
3
4
[root@localhost test]# sed '1,3d' xxx.txt     #刪除1-3 行
4
5
[root@localhost test]# sed '3,$d' xxx.txt     #刪除3到最後一行
1
2

附加

[root@localhost test]# sed '1a test add' xxx.txt  #在第一行後面插入test add
1
test add
2
3
4
5
[root@localhost test]# sed '1,3a test add' xxx.txt   #在第一行到第三行後面都插入test add
1
test add
2
test add
3
test add
4
5
[root@localhost test]# sed '1,3a test1 \ntest2' xxx.txt    #在第一行到第三行後面都插入test1 test2兩行,使用換行符\n
1
test1 
test2
2
test1 
test2
3
test1 
test2
4
5
[root@localhost test]# sed  '$a xxx' xxx.txt     #在最後一行插入xxx
1
2
3
4
5
xxx

替換

[root@localhost test]# sed '1c test' xxx.txt       #將第一行替換爲test
test
2
3
4
5
[root@localhost test]# sed '1,3c test' xxx.txt    #將1-3行替換爲test
test
4
5
[root@localhost test]# sed '/2/p' xxx.txt        #將匹配到的2 打印模式空間中的行
1
2
2
3
4
5
[root@localhost test]# sed 's/2/pp/g' xxx.txt    #將匹配到的2 替換爲pp
1
pp
3
4
5

刪除/boot/grub/grub.conf文件中全部行的行首的空白字符;

[root@localhost test]# cat /boot/grub/grub.conf 
# grub.conf generated by anaconda
#
# Note that you do not have to rerun grub after making changes to this file
# NOTICE:  You have a /boot partition.  This means that
#          all kernel and initrd paths are relative to /boot/, eg.
#          root (hd0,0)
#          kernel /vmlinuz-version ro root=/dev/mapper/VolGroup-lv_root
#          initrd /initrd-[generic-]version.img
#boot=/dev/sda
default=0
timeout=5
splashp_w_picpath=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title CentOS 6 (2.6.32-573.el6.x86_64)
        root (hd0,0)
        kernel /vmlinuz-2.6.32-573.el6.x86_64 ro root=/dev/mapper/VolGroup-lv_root rd_NO_LUKS LANG=en_US.UTF-8 rd_NO_MD rd_LVM_LV=VolGroup/lv_swap SYSFONT=latarcyrheb-sun16 crashkernel=auto rd_LVM_LV=VolGroup/lv_root  KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet
        initrd /initramfs-2.6.32-573.el6.x86_64.img 
[root@localhost test]# sed 's/^[[:space:]]\+//' /boot/grub/grub.conf
# grub.conf generated by anaconda
#
# Note that you do not have to rerun grub after making changes to this file
# NOTICE:  You have a /boot partition.  This means that
#          all kernel and initrd paths are relative to /boot/, eg.
#          root (hd0,0)
#          kernel /vmlinuz-version ro root=/dev/mapper/VolGroup-lv_root
#          initrd /initrd-[generic-]version.img
#boot=/dev/sda
default=0
timeout=5
splashp_w_picpath=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title CentOS 6 (2.6.32-573.el6.x86_64)
root (hd0,0)
kernel /vmlinuz-2.6.32-573.el6.x86_64 ro root=/dev/mapper/VolGroup-lv_root rd_NO_LUKS LANG=en_US.UTF-8 rd_NO_MD rd_LVM_LV=VolGroup/lv_swap SYSFONT=latarcyrheb-sun16 crashkernel=auto rd_LVM_LV=VolGroup/lv_root  KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet
initrd /initramfs-2.6.32-573.el6.x86_64.img

刪除/etc/fstab文件中全部以#開頭,後跟至少一個空白字符的行的行首的#和空白字符;

[root@localhost test]# cat /etc/fstab
#
# /etc/fstab
# Created by anaconda on Mon Sep 21 18:38:21 2015
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/VolGroup-lv_root /                       ext4    defaults        1 1
UUID=8f13d755-9ea5-4250-91d7-e7bb313381d8 /boot                   ext4    defaults        1 2
/dev/mapper/VolGroup-lv_home /home                   ext4    defaults        1 2
/dev/mapper/VolGroup-lv_swap swap                    swap    defaults        0 0
tmpfs                   /dev/shm                tmpfs   defaults        0 0
devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
sysfs                   /sys                    sysfs   defaults        0 0
proc                    /proc                   proc    defaults        0 0
[root@localhost test]# sed 's/^#[[:space:]]\+//' /etc/fstab
#
/etc/fstab
Created by anaconda on Mon Sep 21 18:38:21 2015
#
Accessible filesystems, by reference, are maintained under '/dev/disk'
See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/VolGroup-lv_root /                       ext4    defaults        1 1
UUID=8f13d755-9ea5-4250-91d7-e7bb313381d8 /boot                   ext4    defaults        1 2
/dev/mapper/VolGroup-lv_home /home                   ext4    defaults        1 2
/dev/mapper/VolGroup-lv_swap swap                    swap    defaults        0 0
tmpfs                   /dev/shm                tmpfs   defaults        0 0
devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
sysfs                   /sys                    sysfs   defaults        0 0
proc                    /proc                   proc    defaults        0 0

把/etc/fstab文件的奇數行另存爲/tmp/fstab.3;

[root@localhost test]# sed '1~2w /tmp/fstab.3' /etc/fstab
#
# /etc/fstab
# Created by anaconda on Mon Sep 21 18:38:21 2015
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/VolGroup-lv_root /                       ext4    defaults        1 1
UUID=8f13d755-9ea5-4250-91d7-e7bb313381d8 /boot                   ext4    defaults        1 2
/dev/mapper/VolGroup-lv_home /home                   ext4    defaults        1 2
/dev/mapper/VolGroup-lv_swap swap                    swap    defaults        0 0
tmpfs                   /dev/shm                tmpfs   defaults        0 0
devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
sysfs                   /sys                    sysfs   defaults        0 0
proc                    /proc                   proc    defaults        0 0
[root@localhost test]# cat /tmp/fstab.3
# /etc/fstab
#
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
/dev/mapper/VolGroup-lv_root /                       ext4    defaults        1 1
/dev/mapper/VolGroup-lv_home /home                   ext4    defaults        1 2
tmpfs                   /dev/shm                tmpfs   defaults        0 0
sysfs                   /sys                    sysfs   defaults        0 0

echo一個文件路徑給sed命令,取出其基名;進一步地,取出其路徑名

[root@localhost test]# echo "/etc/sysconfig/network-scripts/" | sed 's@^.*/\([^/]\+\)/\?$@\1@'
network-scripts
[root@localhost test]# echo "/etc/sysconfig/network-scripts/" | sed 's@[^/]\+/\?$@@'
/etc/sysconfig/

 

高級命令:
 h                用模式空間中的內容覆蓋保持空間的內容;
 H               把模式空間中的內容追加至保持空間中內容的後面;
 g               從保持空間中取到其內容,並將其覆蓋模式空間中的內容;
 G               從保持空間中取到其內容,並將其追加在模式空間中的內容的後面;
 x               把保持空間和模式空間中的進行交換;
 n               讀取匹配到的行的下一行至模式空間;(會覆蓋模式空間中的原有內容);
 N               讀取匹配到的行的下一行至模式空間,追加在模式空間中原有內容的後面;
 d               刪除模式空間中的內容;
 D               刪除多行模式空間中的首行;

 注意:命令功能可以使用!取反;分號可用於分隔腳本;

 

示例:
在文件中的每行後方添加空白行

[root@localhost test]# cat /etc/issue
CentOS release 6.7 (Final)
Kernel \r on an \m
[root@localhost test]# sed 'G' /etc/issue
CentOS release 6.7 (Final)
Kernel \r on an \m
 
[root@localhost test]#

保留最後一行

[root@localhost test]# cat /etc/fstab
#
# /etc/fstab
# Created by anaconda on Mon Sep 21 18:38:21 2015
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/VolGroup-lv_root /                       ext4    defaults        1 1
UUID=8f13d755-9ea5-4250-91d7-e7bb313381d8 /boot                   ext4    defaults        1 2
/dev/mapper/VolGroup-lv_home /home                   ext4    defaults        1 2
/dev/mapper/VolGroup-lv_swap swap                    swap    defaults        0 0
tmpfs                   /dev/shm                tmpfs   defaults        0 0
devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
sysfs                   /sys                    sysfs   defaults        0 0
proc                    /proc                   proc    defaults        0 0
[root@localhost test]# sed '$!d' /etc/fstab
proc                    /proc                   proc    defaults        0 0

保證指定的文件每一行後方有且只有一個空白行

[root@localhost test]# cat /etc/issue      
CentOS release 6.7 (Final)
Kernel \r on an \m
[root@localhost test]# sed '/^$/d;G' /etc/issue
CentOS release 6.7 (Final)
Kernel \r on an \m
[root@localhost test]#

保留奇數行

[root@localhost test]# cat /etc/issue          
CentOS release 6.7 (Final)
Kernel \r on an \m
[root@localhost test]# sed 'n;d' /etc/issue
CentOS release 6.7 (Final)
[root@localhost test]#

反向輸出一個文件

[root@localhost test]# cat /etc/issue      
CentOS release 6.7 (Final)
Kernel \r on an \m
[root@localhost test]# sed -n '1!G;h;$p' /etc/issue
Kernel \r on an \m
CentOS release 6.7 (Final)

保留文件的最後兩行

[root@localhost test]# cat /etc/issue              
CentOS release 6.7 (Final)
Kernel \r on an \m
[root@localhost test]# sed '$!N;$!D' /etc/issue
Kernel \r on an \m
[root@localhost test]#

  

三  awk   gawk - pattern scanning and processing language

    Gnu AWK, gawk

     awk [options] 'program' file file ...
     awk [options] 'PATTERN{action}' file file ...

     gawk [ POSIX or GNU style options ] -f program-file [ -- ] file ...
     gawk [ POSIX or GNU style options ] [ -- ] program-text file ...

 

    -F CHAR:輸入分隔符

 

一、awk的輸出
  print item1, item2,...
  要點:
  (1) 各項目之間使用逗號分隔,而輸出時則使用輸出分隔符分隔;
  (2) 輸出的各item能夠字符串或數值、當前記錄的字段、變量或awk的表達式;數值會被隱式轉換爲字符串後輸出;
  (3) print後面item若是省略,至關於print $0;輸出空白,使用pirnt "";

二、awk的變量
  內置變量,自定義變量

    2.1 內置變量
      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,字段數
      NR            Numbers of Record, 行數;全部文件的一併計數;
      FNR           行數;各文件分別計數;
      ARGV          數組,保存命令自己這個字符,awk '{print $0}' 1.txt 2.txt,意味着ARGV[0]保存awk,
      ARGC          保存awk命令中參數的個數;
      FILENAME      awk正在處理的當前文件的名稱;

    2.2 可自定義變量
      -v var_name=VALUE
      變量名區分字符大小寫;
      (1) 能夠program中定義變量;
      (2) 能夠命令行中經過-v選項自定義變量;

三、awk的printf命令
  命令的使用格式:printf format, item1, item2,...
  要點:
  (1) 要指定format;
  (2) 不會自動換行;如需換行則須要給出\n
  (3) format用於爲後面的每一個item指定其輸出格式;

  format格式的指示符都%開頭,後跟一個字符:
  %c        顯示字符的ASCII碼;
  %d, %i    十進制整數;
  %e, %E    科學計數法顯示數值;
  %f        顯示浮點數;
  %g, %G    以科學計數法格式或浮點數格式顯示數值;
  %s        顯示字符串;
  %u        顯示無符號整數;
  %%        顯示%自身;

  修飾符:
  #         顯示寬度
  -         左對齊
  +         顯示數值的符號
  .#        取值精度

四、awk輸出重定向
  print items > output-file
  print items >> output-file
  print items | command

  特殊文件描述符:
  /dev/stdin        標準輸入
  /dev/stdout       標準輸出
  /dev/stderr       錯誤輸出

五、awk的操做符

  算術操做符:
  x+y
  x-y
  x*y
  x/y
  x**y, x^y
  x%y
  -x            負值
  +x            轉換爲數值

  字符串操做符    鏈接

  賦值操做符:
  =
  +=
  -=
  *=
  /=
  %=
  ^=
  **=

  ++
  --

  若是模式自身是=號,要寫爲/=/

  比較操做符:
  <
  <=
  >
  >=
  ==
  !=
  ~         模式匹配,左邊的字符串可以被右邊的模式所匹配爲真,不然爲假;
  !~:

  邏輯操做符:
  &&         與
  ||         或

  條件表達式:
  selector?if-true-expression:if-false-expression

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

  函數調用:
  function_name(argu1,argu2)

六、模式

  (1) Regexp: 格式爲/PATTERN/
    僅處理被/PATTERN/匹配到的行;
  (2) Expression: 表達式,其結果爲非0或非空字符串時知足條件;
    僅處理知足條件的行;
  (3) Ranges: 行範圍,此前地址定界,
    NR
    僅處理範圍內的行
  (4) BEGIN/END: 特殊模式,僅在awk命令的program運行以前(BEGIN)或運行以後(END)執行一次;
  (5) Empty:空模式,匹配任意行;

七、經常使用的action
  (1) Expressions
  (2) Control statements
  (3) Compound statements
  (4) input statements
  (5) output statements

八、控制語句
  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
      # awk '{if (NF>=8) {print}}' /etc/inittab

  8.2 while
      格式:while (condition) {while body}
      # awk '{i=1; while (i<=NF){printf "%s ",$i;i+=2};print ""}' /etc/inittab
      # awk '{i=1; while (i<=NF){if (length($i)>=6) {print $i}; i++}}' /etc/inittab

  length()函數:取字符串的長度

  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}

  8.6 循環控制
      break
      continue

  8.7 next
      提早結束對本行的處理進而提早進入下一行的處理;
      # awk -F: '{if($3%2==0) next;print $1,$3}' /etc/passwd
      # awk -F: '{if(NR%2==0) next; print NR,$1}' /etc/passwd

九、數組
  傳統數組: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的索引;

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

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

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

  刪除數組元素:
  delete array[index]

十、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]}'

  length(string)
  功能:返回給定字串的長度

  substr(string,start[,length])  功能:從string中取子串,從start爲起始位置爲取length長度的子串;

相關文章
相關標籤/搜索