SHELL笔记之让文本飞(四)

1.正则表达式(基本组成部分)
==============================
^   行起始位置     ^tux 匹配以tux起始的行
$  行尾标记         tux$ 匹配以tux结尾的行
.   匹配任意一个字符    Hack.  匹配Hack1和Hacki,但是不能匹配Hack12和Hackil,它只能匹配单个字符
[ ] 匹配[字符]中任意一个字符    coo[kl] 匹配cook和cool
[^] 匹配[^字符]之外的任意一个字符    9[^01]匹配92,93,但不匹配90,91
[-]  匹配[]中指定范围的任意一个字符   [1-5] 匹配从1-5的任意一个数字
?   匹配之前的项一次或0次    colou?r 匹配color或colour,但是不能匹配colouur
+   匹配之前的项一次或多次    Rollno-9+ 匹配Rollno-99,Rollono-9,但是不能匹配Rollon-
*    匹配之前的项0次或多次    co*l  匹配cl,col,cool等
()   创建一个用于匹配的子窜    ma(tri)?x 匹配matrix 或max   
{n} 匹配之前的项n次      [0-9]{3}匹配任意一个三位数,可以扩展为[0-9][0-9][0-9]
{n,} 之前的项至少匹配n次    [0-9]{2,} 匹配任意一个两位数或多位数
{n,m} 指定匹配次数的区间    [0-9]{2,5} 匹配从2位数到5位数之间的任意一个数字
|    交替---匹配|两边的任意一项     Oct(1st | 2nd ) 匹配Oct 1st 或者Oct 2nd
\    转义符可以将上面介绍的特殊字符进行转义   a\.b匹配a.b,但不能匹配ajb。
\1   :引用第一个括号和对应括号中的内容     ( grep  '\(l..e\).*\1)  /etc/network/interface )
=============================================

2  用grep在文件中搜索文本
eg: grep “match_text"   file1  file2...   对多个文件进行搜索
eg: grep  word   filename  --color=auto    输出行中着重标记出匹配到的单词
eg: grep -e ”[a-z]+"  filename    使用正则表达式匹配 (egrep "[a-z]+" filename )
eg:   egrep -o  "[a-z]+\."  filename   只输出文件中匹配到的文本
eg: grep -v  match_pattern file    打印除包含match_pattern行之外的所有行
eg: grep -c  "text"  filename    统计文件或文本中匹配字符串的行数
eg: grep   "text" -n  filename    打印出包含匹配字符串的行号
eg: grep   -b -o  “text” filename   打印模式所位于的字符或字节的偏移 (选项-b 总是配合-o使用 )
eg: grep -l  “linux”  file1  file2    搜索多个文件并找出匹配文本位于哪一个文件中。
eg:  grep  '\<root\>'   /etc/network/interface   匹配文中出现的单词root  ( grep  '\broot\b' /etc/network/interface )
eg: grep  '^\([0-9]\).*\1$'  /etc/inittab     找到文件中以任意数字开头,并且这个数字结尾的行

eg: grep  “text”  src_dir    -R  -n     在多级目录中对文本进行递归搜索(多用于开发人员使用最多的命令之一,用于查找某些文本位于哪些源码文件中) grep选项的-R和-r没有区别
eg: grep -i  “text” filename    忽略大小写的搜索
eg: egrep  "pattern1"  -e   "pattern2"   匹配多个样式
eg: grep -f  pattern_file    source_filename    通过样式文件匹配多个

eg:  grep  “main()"  . -r   --include *.{c,cpp}    在grep搜索中指定文件进行 (some{string1,string2}会扩展成somestring1,somestring2)
eg:   grep  ”main()" . -r   --exclude "README"   在grep搜索中排出某些文件进行 (排出目录用 --exclude-dir )

eg: grep "test" file* -lZ  |  xargs -0 rm    (-Z表示以0值字节作为终结符的文件名)

eg: grep -q    "test" filename      静默输出,不会输出任何信息,如果命令运行成功返回0,失败返回非零。($?)

eg: grep  -A 3  "text"   filename    打印匹配以及之后的3行   (如果有多个匹配,使用--作为部分之间的界定符)
eg:grep -B 3  "text"   filename    打印匹配以及之前的3行
eg:grep -C 3  "text"  filename   打印匹配以及之前之后的各3行

 
3.用cut按列切分文件
cut是一个帮我们将文本按列进行切分的小巧工具。他可以指定分隔列每列的定界符。每列被称为一个字段。
eg: cut  -f  2,3  filename      //显示第2列和第3列   (制表符是字段或列的默认界定符。对于没有界定符的行,会将该行照原样打印出来。如果不想打印出这种不包含界定符的行,则可以使用cut的-s选项。)

eg: cut -f  3  --complement   filename     //补集运算,打印出除第3列的所有列

eg: cut  -f 2  -d ";"   filename  //界定符为“;"分号,打印第2列

eg:cut命令可以将一串指定的字符作为列来显示
      cut -c 1-5  filename  // 打印第1到第5个字符
     cut -c -2  filename    //打印前2个字符
     注释: (-c表示字符;-b表示字节;-f用于定义字段 )
     (N- :从第N个字节,字符或字段到行尾 ;      N-M:从第N个字节,字符或字段到第M个(包括第M个在内)字节,字符或字段  ;           -M:  从第1个字节,字符或字段到第M个(包括第M个在内)字节,字符或字段 。)

eg: cut  filename   -c1-3,6-9  --output-delimiter ","    //当用-b或-c提取多个字段时,必须使用--output-delimiter,否则就没法区分不同的字段了。



4.sed命令(流编辑器stream editor)文本替换
4.1eg: sed可以替换给定文本中的字符串
sed 's/pattern/replace_string/' file
cat  file | sed 's/pattern/replace_string/'

4.2 替换的同时保存文本(-i选项)
  sed -i  's/text/replace/' file

4.3前面的sed命令只会替换每一行中第一处符合模式的内容,但是如果想全部替换,需要加上参数g
   sed  's/pattern/replace_string/g'   file    //全部替换
   sed  's/pattern/replace_string/2g'   file  //从每一行的第2处开始匹配替换(/Ng 选项)

4.4当界定符出现在样式内部时,必须用前缀\对它进行转义
     sed    's|te\|xt|replace|g'
    (字符/在sed中被作为定界符使用,我们也可以使用”:"冒号;“|”一树作为界定符。)

4.5移除空白( /pattern/d 会移除匹配样式的行)
    sed '/^$/d' filename

4.6使用指定的数字替换文件中所有3位数的数字
  sed -i 's/\b[0-9]\{3\}\b/NUMBER/g'  filename       (\b表示单词边界)

4.7相对上面的做法,一种有益的做法是替换前,先备份
 sed -i  .bak  's/\b[0-9]\{3\}\b/NUMBER/g'  filename     //备份文件为filename.bak

4.8已匹配字符串标记(&)
eg:  echo this is an example | sed 's/\w\+/[&]/g'      // [this] [is] [an] [example]   (正则表达式\w\+匹配每一个单词,然后我们用[&]替换它。&对应于之前所匹配到的单词。)
 
4.9子串匹配标记(\1)
eg:  echo this is  digit 7 in a number | sed 's/digit\([0-9]\)/\1/'        // this is 7 in a number  (这条命令将digit 7替换为7。样式中匹配到的子串是7。\(pattern\)用于匹配子串。模式被包括在使用斜线转义过的()中。对于匹配到的第一个子串,其对应的标记是\1,匹配到的第二个子串是\2,往后依次类推。

eg:  echo seven EIGHT | sed 's/\([a-z]\+\) \([A-Z]\+\)/\2 \1/'     //    EIGHT   seven   

4.10组合多个表达式
sed 'expression'  | sed  'expression'  等价于   sed 'expression;  expression'   等价于   sed -e 'expression'  -e   'expression'
eg:  echo  abc  | sed  's/a/A/'  | sed 's/c/C/'         
       echo  abc  |  sed 's/a/A/' ; s/c/C/'
       echo abc | sed -e 's/a/A/' -e 's/c/C/'

4.11引用
  sed通常用单引号来引用。不过也可以使用双引号。双引号会通过对表达式求值来对其进行扩展。
eg: text=hello
         echo hello world | sed "s/$text/HELLO/"    //结果: HELLO world



5. awk
基本结构:  awk 'BEGIN{ print "start" } pattern { commands } END{print "end" }'  file
  BEGIN语句块在awk开始从输入流中读取行之前被执行。这是一个可选的语句块,诸如变量初始化,打印输出表格的表头等语句通常都可以写入BEGIN语句块中。
  END语句块在awk从输入流中读取完所有的行之后即被执行。像打印所有行的分析结果这类汇总信息。
  pattern语句块,awk每读取一行,就会检查改行和提供的样式是否匹配。样式本身可以是正则表达式,条件语句以及行匹配范围等。

5.1特殊变量
    NR:表示记录数量,在执行的过程中对应于当前行号。
    NF:表示字段数量,在执行的过程中对应于当前行的字段数。
    $0: 这个变量包含执行过程当中当前行的文本内容。
    $N: 表示第N段的文本内容(0<N<NF )

eg: awk 'END{print NR}' filename    //统计文件中的行数
eg: awk 'BEGIN{sum=0}{sum+=$1}END{print sum}'  filename  //将每行中第一个字段的值累加

5.2将外部变量值传递给awk
 eg:var=3000;   echo | awk -v   variable=$var '{print variable}'    //结果为:3000
eg: var1="hello";var2="world"
         echo | awk '{print v1,v2}' v1=$var1 v2=$var2     //结果为: hello world

5.3用getline读取行(只读取某一行)
eg:  seq 5 | awk 'BEGIN{getline;print $0}'    //结果为: 1

5.4使用过滤模式对awk处理进行过滤
  eg: awk 'NR<5'    //行号小于5
  eg: awk 'NR==1,NR==4'   //行号在1到5之间的行
  eg: awk '/linux/'      //包含样式linux的行(可以用正则表达式来指定模式)
  eg: awk '!/linux/'    //不包含模式linux的行

eg: awk 'NR==4,NR==8' filename    //打印从4行到8行的数据
eg: awk '/start_pattern/, /end_pattern/'  filename     //打印处于两种样式之间的文本

5.5设置字段定界符
eg: cat /etc/passwd | awk 'BEGIN{FS=":"}{print $1}'     //打印出所有的用户名(以冒号为定界符)


5.6统计特定文件中的词频
#!/bin/bash
#filename:word_freq.sh
#use to count the word
if [ $# -ne 1 ];
then
    echo "Usage: $0 filename";
    exit -1
fi
filename=$1
egrep -o "\b[[:alpha:]]+\b" $filename | awk '{ count[$0]++ }END{printf("%-14s%s\n","word","count");for(ind in count){printf("%-14s%d\n",ind,count[ind]);} }'
 

6.压缩或解压缩JavaScript
6.1 压缩    
    cat sample.js  | tr -d '\n\t' | tr -s ' '  | sed 's:/\*.*\*/::g'   | sed 's/ \?\([{}();,:]\) \?/\1/g'

6.2解压
    cat obfuscated.txt  | sed 's/;/;\n/g;  s/{/{\n\n/g; s/}/\n\n}/g'

6.3说明
   eg: tr -d '\n\t'    //移除'\n'和‘\t'
   eg: tr -s ' '  或者  sed 's/[ ]+/ /g'    //移除多余的空格
   eg: sed  's:/\*.*\*/::g'     //移除注释
   eg: sed  's/ \?\([{}();,;]\) \?/\1/g'    //移除{,},(,),;,: 以及,以及前后的空格

7.按列合并多个文件(paste命令)
eg: paste file1 file2 file3...     //默认使用制表符为定界符
eg:  paste file1 file2 file3 -d ","     //使用-d指明定界符


8.以逆序形式打印行(tac命令)
eg: tac filename    //逆序打印文件(默认是换行符为分隔符,但可以使用-s来指定分隔符)
eg:seq 9 | awk '{lifo[NR]=$0}END{for(lno=NR;lno>-1;lno--)(print lifo[lno]; } }'    //使用awk方式实现

9.解析文本中的电子邮件和URL
9.1电子邮件
  egrep -o   "[A-Za-z0-9._]+@[A-Za-z0-9.]+\.[a-zA-Z]{2,4}"   filename

9.2 URL
egrep  -o "http://[a-zA-Z0-9.]+\.[a-zA-Z]{2,3}" filename

10.移除文本中包含的某个单词或句子
eg:   sed 's/ [^.]*mobile phones[^.]*\.//g'  filename      //移除文本中的mobile phones

11.对目录中的所有文件进行替换
eg: find . -name *.cpp -print0 | xargs -I {} -0 sed -i 's/Copyright/Copyleft/g' {}    //将当前目录下所有cpp文件中的copyright替换成copyleft

eg: find . -name *.cpp -exec sed -i  's/Copyright/Copyleft/g' \{\} \;
         find . -name *.cpp -exec sed -i  's/Copyright/Copyleft/g' \{\} \+
后面两个也可以实现同样的功能,但第一个exec命令会为每个查找到的文件调用一次sed,而第二个命令中,find会将多个文件名一并传给sed


12文本切片及参数操作
eg: 替换变量内容中的部分文本
var="This is a line of text"
echo ${var/line/REPLACED}    //结果:This is a REPLACED of text

eg:通过指定字符串的起始位置和长度来生成子串,语法: ${variable_name:start_position:length}
string=abcdefghijklmnopqrstuvwxyz
echo  ${string:4}    //结果:efghijklmnopqrstuvwxyz  (打印第5个字符之后的内容)
echo ${string:4:8}  //结果:efghijkl   (从第5个字符开始,打印8个字符)
echo ${string:(-1)}   //结果: z   (从后向前计数,将最后一个字符索引记为-1 )
echo ${string:(-2):2} //结果: yz

你可能感兴趣的:(SHELL笔记之让文本飞(四))