读《Linux Shell脚本攻略》第4章笔记

  • A+
所属分类:Shell

1. 正则表达式
正则表达式的基本组成部分:
^       行起始标记
$      行尾标记
.       匹配任意一个字符
[]      匹配包含在[字符]之中的任意一个字符
[^]     匹配除[^字符]之外的任意一个字符
[-]     匹配[]中指定范围内的任意一个字符
?      匹配之前的项1次或0次
+      匹配之前的项1次或多次
*       匹配之前的项0次或多次
()      创建一个用于匹配的子串,例如:ma(tri)?匹配max或maxtrix
{n}    匹配之前的项n次
{n,}   之前的项至少需要匹配n次
{n,m} 指定之前的项所必需匹配的最小次数和最大次数
|        匹配|两边的任意一项
\        转义符可以将上面介绍的特殊字符进行转义

POSIX字符类是一个形如[:...:]的特殊元序列(meta sequence),它可以用于匹配特定的字符范围。
POSIX字符表如下:
[:alnum:] 字符与数字字符
[:alpha:] 字母字符(包括大写字母与小写字母)
[:blank:] 空格与制表符
[:digit:] 数字字符
[:lower:] 小写字母
[:upper:] 大写字母
[:punct:] 标点符号
[:space:] 包括换行符、回车等在内的所有空白字符

元字符是一种Perl风格的正则表达式,只有一部分文本处理工具支持它,并不是所有的工具支持它
\b 单词边界
\B 非单词边界
\d 单个数字字符
\D 单个非数字字符
\w 单个单词字符(字母、数字与_)
\W 单个非单词字符
\n 换行符
\s 单个空白字符
\S 单个非空白字符
\r 回车

2. grep
grep match_pattern filename或者grep “match_pattern” filename
this is the line containing match_pattern #命令会返回包含给定match_pattern的文本行

[root@server1 test]# echo -e “this is a word\nnext line” | grep word –color=auto
this is a word

grep命令通常将match_pattern视为通配符。如果要使用正则表达式,需要添加-E(extended)使用扩展正则表达式,也可以使用默认允许正则表达式的grep命令—egrep
[root@server1 test]# echo -e “www.linuxeye.com 43243\n4444″ | grep -E “[a-z]+”
www.linuxeye.com 43243
[root@server1 test]# echo -e “www.linuxeye.com 43243\n4444″ | egrep “[a-z]+”
www.linuxeye.com 43243

#选项-o只输出文本中匹配到的文本部分
[root@server1 test]# echo -e “www.linuxeye.com 43243\n4444″ | egrep -o “[a-z]+”
www
linuxeye
com

#选项-v(invert)将匹配结果进行反转
[root@server1 test]# echo -e “www.linuxeye.com 43243\n4444″ | egrep -v “[a-z]+”
4444

#-c统计匹配行的数量,并不是匹配的次数
[root@server1 test]# echo -e “www.linuxeye.com 43243\n4444\n3333″ | egrep -vc “[a-z]+”
2

#-n打印出包含匹配字符串的行号
[root@server1 test]# echo -e “www.linuxeye.com 43243\n4444\n3333″ | egrep -vn “[a-z]+”
2:4444
3:3333

#-b打印样式匹配所位于的字符或字节偏移,一行中字符串的字符偏移是从该行的第一个字符开始计算,起始值是0
[root@server1 test]# echo -e “www.linuxeye.com 43243\n4444\n3333″ | egrep -vb “[a-z]+”
23:4444
28:3333

#-l搜索多个文件并找出匹配文本位于哪一个文件中 -l相反选项-L,它会返回一个不匹配的文件列表
[root@server1 test]# grep -l line2 *
version1.txt
version2.txt
version.patch

[root@server1 test]# grep -L line2 *
filestat.sh
other
out.html
remove_duplicates.sh
test
test_copy1
test_copy2

#-R递归搜索文件
[root@server1 test]# grep -Rn “text” .

#-i忽略样式中的大小写
[root@server1 test]# echo www.LINUXEYE.COM | grep -i linuxeye
www.LINUXEYE.COM

#-e匹配多个样式中的一个
[root@server1 test]# echo www.LINUXEYE.COM | grep -ie linx -e com
www.LINUXEYE.COM

#-f与-e选项以后,-f在样式文件中逐行写下匹配的样式
[root@server1 test]# cat pat_file
hello
cool
[root@server1 test]# echo “hello this is cool” | grep -f pat_file
hello this is cool

#在grep搜索中包含或排除文件
只在目录中递归搜索所有的.c和.cpp文件
[root@server1 test]# grep “main()” /usr -r –include *.{c,cpp}
/usr/src/kernels/2.6.18-194.el5PAE-i686/scripts/kconfig/gconf.c: gtk_main();

在搜索中排除所有的README文件
[root@server1 test]# grep “main()” . -r –exclude “README”
如果需要排除目录,可以使用–exclude-dir选项
如果需要从文件中读取所需排除的文件列表,使用–exclude-from FILE

使用0值字节后缀的grep与xargs
[root@server1 test]# echo test > file1
[root@server1 test]# echo cool > file2
[root@server1 test]# echo test > file3
[root@server1 test]# grep “test” file* -lZ | xargs -0 rm

grep的静默输出
-q(quiet mode)
[root@server1 test]# cat file2
cool
[root@server1 test]# grep -q ‘co’ file2 ;echo $?
0
[root@server1 test]# grep -q ‘cookk’ file2 ;echo $?
1

打印出匹配文本的之前行或之后行
[root@server1 test]# seq 10 | grep 5 -A 3
5
6
7
8
[root@server1 test]# seq 10 | grep 5 -B 3
2
3
4
5
[root@server1 test]# seq 10 | grep 5 -C 2
3
4
5
6
7

3. cut
[root@server1 test]# cat data.txt
No Name Mark Percent
1 Sarath 45 90
2 Alex 49 98
3 Anu 45 90
[root@server1 test]# cut -f 1,4 data.txt
No Percent
1 90
2 98
3 90

#-complement选项对提前的字段进行补集运算
[root@server1 test]# cut -f3 –complement data.txt
No Name Percent
1 Sarath 90
2 Alex 98
3 Anu 90

要指定字段的定界符,使用-d选项
[root@server1 test]# cat data1.txt
No;Name;Mark;Percent
1;Sarath;45;90
2;Alex;49;98
3;Anu;45;90
[root@server1 test]# cut -f2,4 -d”;” data1.txt
Name;Percent
Sarath;90
Alex;98
Anu;90

-b表示字节;-c表示字符;-f表示定义字段
[root@server1 test]# cut -c-3 data1.txt
No;
1;S
2;A
3;A
[root@server1 test]# cut -c2-4 data1.txt
o;N
;Sa
;Al
;An

4. 统计特定文件中的词频
[root@server1 test]# cat word_freq.sh
#!/bin/bash
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]);}
}’

egrep -o “\b[[:alpha:]]+\b” $filename用来只输出单词。用-o选项打印由换行符分隔的匹配字符序列。
\b是单词边界标记符。[:alpha:]是表示字母的字符类。

5. sed
[root@server1 test]# echo linuxeye.com linuxeyelinuxeyelinuxeye | sed ‘s/linuxeye/LINUXEYE/’
LINUXEYE.com linuxeyelinuxeyelinuxeye
[root@server1 test]# echo linuxeye.com linuxeyelinuxeyelinuxeye | sed ‘s/linuxeye/LINUXEYE/g’
LINUXEYE.com LINUXEYELINUXEYELINUXEYE
[root@server1 test]# echo linuxeye.com linuxeyelinuxeyelinuxeye | sed ‘s/linuxeye/LINUXEYE/2g’
linuxeye.com LINUXEYELINUXEYELINUXEYE
[root@server1 test]# echo linuxeye.com linuxeyelinuxeyelinuxeye | sed ‘s/linuxeye/LINUXEYE/4g’
linuxeye.com linuxeyelinuxeyeLINUXEYE
[root@server1 test]# echo linuxeye.com linuxeyelinuxeyelinuxeye | sed ‘s/linuxeye/LINUXEYE/2′
linuxeye.com LINUXEYElinuxeyelinuxeye
[root@server1 test]# echo linuxeye.com linuxeyelinuxeyelinuxeye | sed ‘s/linuxeye/LINUXEYE/4′
linuxeye.com linuxeyelinuxeyeLINUXEYE
不带参数g会将每一行中第一处符合样式的内容替换掉;带参数g则替换所有内容;数字表示从N处匹配开始替换
参考://blog.linuxeye.com/linux/104.html

6. awk
//blog.linuxeye.com/linux/105.html
# echo -e “line1 f2 f3\nline2 f4 f5\nline3 f6 f7″ | awk ‘{ print “line
no: ” NR “,No of fields:” NF “,$0=”$0 ” ,$1=”$1 ” ,$2=”$2}’
line no: 1,No of fields:3,$0=line1 f2 f3 ,$1=line1 ,$2=f2
line no: 2,No of fields:3,$0=line2 f4 f5 ,$1=line2 ,$2=f4
line no: 3,No of fields:3,$0=line3 f6 f7 ,$1=line3 ,$2=f6

# seq 5 | awk ‘BEGIN{ sum=0; print “Summation:” }{ print $1″+”;sum+=$1 } END { print “==”; print sum }’
Summation:
1+
2+
3+
4+
5+
==
15

# VAR=1000
# echo | awk -v VARIABLE=$VAR ‘{ print VARIABLE }’

# var1=1; var2=2
# echo | awk ‘{print v1,v2}’ v1=$var1 v2=$var2
1 2

#getline读取行
# seq 5 | awk ‘BEGIN { getline;getline;print “test:”$0}{print $0}’
test:2
3
4
5

#用样式对awk出来的行进行过滤
awk ‘NR < 5′ #行号小于5的行
awk ‘NR==2,NR==4′ #行号在2到4之间的行
awk ‘/linuxeye/’ #包含样式linuxeye的行
awk ‘!/linuxeye/’ #不包含样式linuxeye的行

#设置字段定界符
# awk -F: ‘{print $NF}’ /etc/passwd
或者
awk ‘BEGIN { FS=”:” } {print $NF}’ /etc/passwd

#从awk中读取命令输出
# echo | awk ‘{ “grep root /etc/passwd” | getline cmdout; print cmdout }’

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

8. 按列合并文件
[root@server1 test]# paste paste1 paste2
1 test
2 linuxeye
3 com
4 linux
5 opensource
[root@server1 test]# cat paste1
1
2
3
4
5
[root@server1 test]# cat paste2
test
linuxeye
com
linux
opensource
[root@server1 test]# paste paste1 paste2
1 test
2 linuxeye
3 com
4 linux
5 opensource

#默认的定界符是制表符,也可以用-d明确指定定界符,如下:
[root@server1 test]# paste paste1 paste2 -d “:”
1:test
2:linuxeye
3:com
4:linux
5:opensource

9. 用脚本验证回文字符串
sed命令能够记住之前匹配的子样式(sub pattern)。这被称为反向引用。我们可以借助这项功能解决回文问题。
# cat match_palindrome.sh
#!/bin/bash
if [ $# -ne 2 ];
then
echo “Usage: $0 filename string_length”
exit -1
fi

filename=$1
basepattern=’/^\(.\)’
count=$(( $2 / 2 ))
for((i=1;i<$count;i++)) do basepattern=$basepattern’\(.\)’; done if [
$(( $2 % 2 )) -ne 0 ]; then basepattern=$basepattern’.'; fi
for((count;count>0;count–))
do
basepattern=$basepattern’\'”$count”;
done
basepattern=$basepattern’$/p’
sed -n “$basepattern” $filename

rev逆向打印出每一行内容
echo this is linuxeye.COM | rev | tr ‘ ‘ ‘\n’ | tac | tr ‘\n’ ‘ ‘ | rev

10. awk实现head、tail和tac
head /etc/passwd awk实现:awk ‘NR<=10′ /etc/passwd
tail /etc/passwd awk实现:awk ‘{ buffer[NR%10]=$0;} END {
for(i=1;i<11;i++) { print buffer[i%10]}}’ /etc/passwd tac /etc/passwd
awk实现:awk ‘{ buffer[NR] = $0; } END { for(i=NR;i>0;i–) { print
buffer[i] } }’ /etc/passwd

11. 文本切片与参数操作
# var=”This is a line of text”
# echo ${var/line/REPLACED}
This is a REPLACED of text

# string=http://www.linuxeye.com
# echo ${string:7} #打印第7个字符之后的内容
www.linuxeye.com
# echo ${string:11:8} #从第11个字符开始,打印8个字符
linuxeye

其实字符的索引从0开始计数。我们也可以从后向前计数,将最后一个字符索引计为-1.但如果使用负数作为索引值得话,必须将负数放入括号内,例如(-1)就是最后一个字符的索引
# echo ${string:(-12):8}
linuxeye

Mon Jan 7 15:15:52 CST 2013

avatar

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: