接触了shell之后,才发觉原来脚本语言跟传统语言c c++ Java比有其强大的一面。脚本语言能让开发者快速方便的开发,它的开发速度比传统语言快了很多。我喜欢linux,从大一就开始了,说来惭愧,这个喜欢只是停留在表面,并没有因为喜欢linux而专心研究Linux,觉得当时喜欢得很幼稚。其实喜欢一样东西应该更多地了解它,并能为它作贡献。从现在开始潜心学习linux,学习linux绕不过shell的学习。所以呢开始shell的学习。下面是学习的一些笔记,没怎么整理。
脚本编程语言的好处是脚本语言多半运行在比编译型语言还高的层级,能够轻易处理文件与目录之类的对象。花一个小时写成的简单脚本,同样功能用C或C++来编写,可能需要两天时间。shell 是各unix形态之间通用的功能,并且经过了posix的标准化。shell脚本“用心写”一次,即可应用到很多系统上。shell脚本的优点是:1 简单性,shell是一个高级语言,通过它,可以简洁地表达复杂的操作;2 可移植性,使用posix定义的功能,可以做到脚本无须修改就可以在不同的系统上执行;3 开发容易,可以在短时间内完成一个功能强大又好用的脚本。
1 who 查看当前的系统有谁登陆
#who
2 计算用户的个数可以用wc(wc是字数计算)程序,wc可以算出行数(line) 字数(word)和字符数(character)。这个例子中—查看登陆的用户的个数,只需要计算行数就行,
用wc -l 就行。
整个命令就是:who | wc -l 计算以登陆的用户的个数 其中 | 是管道符号。管道符号 | 可以在两个程序之间建立管道:who的输出,成了wc的输入。其中wc所列出的结果就是以登陆用户的个数。
#who | wc -l
3 将管道转变成一个独立的命令。方法就是将这条命令输入一个一般的文件中,然后使用chmod为该文件设置执行的权限。方法如下:
# cat > nusers 建立文件,使用cat复制终端的输入
who | wc -l 程序的内容
^D Ctrl-D表示end-of-file
# chmod +x nusers 让文件拥有执行的权限
#./nusers 执行测试
2 输出执行结果
小型shell脚本的典型开发周期:首先:直接在命令行(终端上)测试。然后:一旦找到能够完成工作的适当语法,再将他们放进一个独立的脚本里,并为该脚本设置执行的权限。之后就直接使用该脚本。
4 脚本文件中的第一行 #!,这表示调用哪个shell解释器,因为shell有很多版本。例如:有一个csh脚本,名为/usr/ucb/whizprog 它的第一行为:#! /bin/csh -f 则执行whizprog -q /dev/tty01 这条命令时,内核解释#!这行后,会以如下的方式来引用csh: /bin/csh -f /usr/ucb/whizprog -q /dev/tty01 需要注意的地方是:#!后面的长度是有限制的,尽量不要超过64个字符。别在选项(option)之后放置任何空白,因为空白会跟着选项一起传递给被引用的程序。还有不同的系统,shell解释器的路径可能会有不同
5 shell 的命令与参数
命令名称 选项 参数 如: ls -l word.c
选项以减号加一个字母 -l 这个选项是可有可无的,有可能需要加上参数(有些需要)。 不需要参数的选项可以合并。如:ls -l -t word.c 可以合并成 ls -lt word.c
选项的开头是一个减号还是两个减号,视程序而定。例如: patch --verbose --backup -p1 < /tmp/whizprog-1.1-1.2-patch < /tmp/whizprog-1.1-1.2-patch 是一个I/O重定向。它会使得patch从 /tmp/whizprog-1.1-1.2-patch文件而不是从键盘读取输入。一两个减号来(--)表示选项结尾的用法。自此之后命令行上看起来像选项的任何项目,都将一视同仁地当成参数处理。 shell命令中分号(;)可用来分隔同一行里的多条命令。shell 会依次执行这些命令。如果使用&符号而不是分号,则shell将在后台执行其前面的命令,这意味着shell不用等到该命令完成,就可以继续执行下一个命令。
6 shell 识别三种基本命令:内建命令,shell函数以及外部命令
内建命令: 内建命令由shell本身所执行的命令。有些命令由于其必要性才内建。如cd用来改变目录,read会将来自用户(或文件)的输入数据传给shell变量。另一种内建命令的存在则是为了效率,最典型的就是test命令。还有I/O命令,如echo与printf
shell函数是功能健全的一系列程序代码,以shell语言写成,它们可以像命令那样引用。
外部命令是由shell的副本(新的进程)所执行的命令。
7 变量名赋值的方式为: 先写变量名称,紧接着=字符,最后是新值,中间完全没有任何空格。当你想取出shell变量的值时,需要在变量名前加上$字符。当所赋予的值内含空格时,要加上引号。如:
first=isaac middle=bashevis last=singer 单行可进行多次赋值
fullname="isaac bashevis singer" 值中包含空格时使用引号
oldname=$fullname 此处不需要引号
fullname="$first $middle $last" 这里需要双引号
8 echo 输出
echo 命令只会将参数打印到标准输出,参数之间以一个空格隔开,并以换行符号结尾。如
echo now is my time
echo -n "Enter your name:" 显示提示
Enter your name: _ 键入数据
echo 有很多转义序列
9 printf 输出
printf命令模仿C程序苦的printf()函数,功能使用方法一模一样.如:
printf "Hello, world\n"
printf 语法:printf format-string [arguments ...] ([] 表示可以不要参数)
如: printf "The first program always prints ' %s, %s! ' \n" Hello world
10 基本的I/O重定向
默认情况下:unix程序会读取标准输入,写入标准输出,并将错误信息传递到标准错误输出。这类程序长叫做过滤器(filter)。默认的标准输入 标准输出以及标准错误输出都是终端,这可以通过cat程序得知:
cat 未指定任何参数,读取标准输入,写入标准输出
now is the time 由用户键入
now is the time 由cat返回
for all good men
for all good men
11 重定向与管道
以 < 改变标准输入
program < file 可将program的标准输入修改为file
tr -d '\r' < dos-file.txt ...
以 > 改变标准输出
program > file 可将program的标准输出修改为file
tr -d '\r' < dos-file.txt > unix-file.txt
这条命令会先以tr将dos-file.txt里的ASCII carriage-return(回车)删除,再将转换完成的数据输出到unix-file.txt。dos-file.txt里的原始数据不会有变化。
> 重定向符在目标文件不存在时,会新建一个。然而,如果目的文件以存在,它就会被覆盖掉;原本的数据都会丢失。
以 >> 附加到文件
program >> file 可将program的标准输出附加到file的结尾处
如同 > ,如果目标文件不存在, >> 重定向符便会新建一个。然而,如果目的文件存在,它不会直接覆盖掉文件,而是将程序所产生的数据附加到文件结尾处;如
for f in dos-file*.txt
do
tr -d '\r' < $f >> big-unix-file.txt
done
以 | 建立管道
program1 | program2可将program1的标准输出修改为program2的标准输入。
< 与 > 可将输入与输出连接到文件,不过管道可以把两个以上执行中的程序衔接在一起。第一个程序的标准输出可以变成第二个程序的标准输入。这样的好处是,管道可以使得执行速度比使用临时文件的程序快上十倍。如:
tr -d '\r' < dos-file.txt | sort > unix-file.txt
这条管道会先删除输入文件内的回车字符,在完成数据的排序之后,将结果输出到目的文件
12 特殊文件: /dev/null 与 /dev/tty
unix系统提供了两个对shell编程特别有用的特殊文件。第一个文件 /dev/null ,就是位桶(bit bucket)。传送到此文件的数据都会被系统丢掉。当程序将数据写到次文件时,会认为它已成功写入数据的操作,但实际上什么事都每作。如果只要命令的退出状态,而不是它的输出,次功能会很有用。如,测试一个文件是否包含某个模式
if grep pattern myfile > /dev/null
then
... 找到模式时
else
... 找不到模式时
fi
相对地,读取 /dev/null 则会立即返回文件结束符号(end-of-file)。读取 /dev/null 的操作很少会出现在shell程序里。
另一个特殊文件为 /dev/tty 。当程序打开此文件时, unix会自动将它重定向到一个终端,再与程序结合。这在程序必须读取人工输入时(例如密码)特别有用。此外,用它来产生错误信息也很方便,只是比较少人这么做。例如:
printf "Enter new password: " 提示输入
stty -echo 关闭自动打印输入字符的功能
read pass < /dev/tty 读取密码
printf "Enter again:" 提示再输入一次
read pass2 < /dev/tty 再读取一次以确认
stty echo 别忘了打开自动打印输入字符的功能
13 位置参数指的是shell脚本的命令行参数。在shell函数里,也可以是函数的参数。各参数都由整数来命名。基于历史的原因,当它超过9,就应该用大括号把数字框起来。如:
echo first arg is $1
echo tenth arg is ${10}
此外,通过特殊变量,我们还可以取得参数的总数,以及一次取得所有参数。
如:想知道某个用户正使用的终端是什么
#who | grep waterhsu
14 简单的执行跟踪
#sh -x nusers 打开执行跟踪功能
+ who 被跟踪的命令
+ wc -l
2 实际的输出
也可以在脚本里用set -x 命令将执行跟踪的功能打开,然后再用set +x 命令关闭
# cat > trace1.sh 建立脚本
#! /bin/sh
set -x 打开跟踪功能
echo 1st echo 做些事
set +x 关闭跟踪功能
echo 2nd echo 再做些事
^D 以end-of-file结尾
2012年10月31日 星期三 13时39分00秒
shell 正则表达式
15 shell中用grep程序查找文本非常方便。grep可以在两种正则表达式风格中选择一种(BRE和ERE),或时执行简单的字符串匹配。BRE是基本正则表达式,ERE是扩展正则表达式。传统上有三种程序,是grep,egrep和fgrep。现在都集成到grep中了,grep中使用选项来选择不同的程序。grep -E 可以取代传统的egrep,grep -F 可以取代传统的fgrep。
16 正则表达式是一种表达方式,可以用来查找匹配特定准则的文本,如"以字母a开头",此表示法可以写一个表达式,选定或匹配多个数据字符串。除了传统的正则表达式表示法之外,现在的正则表达式还可以做到:1 编写正则表达式,它表示特定与locale的字符序列顺序和等价字符。2 编写正则表达式,而不必关心系统底层的字符集是什么。和多unix工具程序沿用某一种正则表达式来强化本身的功能。如:1 寻找匹配文本行的grep工具族:grep egrep 。 2 用来改变输入流的sed流编辑器。 3 字符串处理程序语言awk Icon Perl Python Ruby Tcl等。3 文本查看程序(也称为分页程序,pagers),more page pg less 。 4 文本编辑器,ed行编辑器,标准的vi屏幕编辑器,emacs jed jove vile vim
17 从根本上来看,正则表达式是由两个基本组成部分所建立:一般字符和特殊字符。一般字符指的是任何没有特殊意义的字符,某些情况下,特殊字符也可以视为一般字符。特殊字符常称为元字符。
字符 BRE/ERE 模式含义
\ 两者都可 通常用以关闭后续字符的特殊意义。有时则是相反地打开后续字符
的特殊意义。如\(...\) 与\{...\},其实这就是转义字符
. 两者都可 匹配任何单个的字符,但NULL除外,独立程序一个可以不允许匹配换行字符
* 两者都可 匹配在它之前的任何数目(或没有)的单个字符。以ERE而言,此前置字符可
以是正则表达式,例如:因为.(点号)表示任一字符,所以.*代表“匹配
任一字符的任意长度”。以BRE来说,*若置于正则表达式的第一个字符,
不具有任何特殊意义。
^ 两者都可 匹配紧接着的正则表达式,在行或字符串的起始处。BRE:仅在正则表达式的开头
处具此特殊含义,ERE:置于任何位置都具特殊含义
$ 两者都可 匹配前面的正则表达式,在字符串或行结尾处。BRE:仅在正则表达式结尾处具
特殊含义。ERE:置于任何位置都具特殊含义。
[...] 两者都可 方括号表达式,匹配方括号内的任一字符。连字符(-)指的是连续字符的范围(
注意:范围会因locale而有所不同,因此不具有可移植性)。[abcd],可以匹配a或b或c或d。
[a-z]匹配所有的小写字母(单个),[0-9]匹配数字,^符号置于方括号里
第一个字符则由反向含义:指的是匹配不在列表内(方括号内)的任何字符。作为
首字符的一个连接符或是结束方括号(]),则被视为列表的一部分。所有其他meta(特殊字符)
字符也为列表的一部分(也就是根据其字面上的意义,就是一般字符)。方括号表达式
里可能会含有排序符号,等价字符集,以及字符集。
\{n,m\} BRE 区间表达式,匹配在它前面的单个字符重现的次数区间。a\{3\}指的是a重现3次;a\{3,\}
则表示a至少重现3次;a\{3,10\}指的是a重现3至10次。n和m的值必须介于0至RE_DUP_MAX
之间,后者最小值是255。可以用命令getconf RE_DUP_MAX来查看系统的这个值
\( \) BRE 将\(与\)间的模式存储在特殊的“保留空间”。最多可以将9个独立的子模式存储在单个模式中。
匹配于子模式的文本,可通过转义序列 \1 至\9,被重复使用在相同模式里。如:\(ab\).*\1,
指的是匹配于ab组合的两次重现,中间可存在任何数目的字符。
\n BRE 重复在\(与\)方括号内第n个子模式至此点的模式。n为1至9的数字,1为由左开始。
(n,m) ERE 与先前提及BRE的\{n,m\}一样,只不过方括号前没有反斜扛
+ ERE 匹配前面正则表达式的一个或多个实例
? ERE 匹配前面正则表达式的零个或一个实例
| ERE 匹配与|符号前或后的正则表达式
() ERE 匹配与方括号阔起来的正则表达式群
例子:
表达式 匹配
tolstoy 位于一行上任何位置的7个字母:tolstoy
^tolstoy 7个字母tolstoy,出现在一行的开头
tolstoy$ 7个字母tolstoy,出现在一行的结尾
^tolstoy$ 正好包括tolstoy这7个字母的一行,没有其他的任何字符
[Tt]olstoy 在一行上的任意位居中,含有Tolstoy或是tolstoy
tol.toy 在一行上的任意位居中,含有tol这3个字母,加上任何一个字符,再接着toy这3个字母
tol.*toy 在一行上的任意位居中,含有tol这个3个字母,加上任意的0或多个字符,再继续toy这3个字母
如toltoy,tolstoy,tolWHHHfffoootoy等等
18 方括号表达式:方括号表达式里除了字面上的字符之外,另有额外的组成部分,包括:
字符集:
以[:与:]将关键子组合括起来的POSIX字符集。关键字描述各种不同的字符集,如英文字母字符,控制字符
排序符号
排序符号指的是将多字符序列视为一个单位。它使用[.与.]将字符组合括起来。排序符号在系统所使用的特定locale上各有其定义。
等价字符集
等价字符集列出的是应视为等值的一组字符,它由取自于locale的名字元素组成,以[=与=]括住。
这三种构造都必须使用方括号表达式。例如[[:alpha:]!]匹配任一英文字母字符或!。而[[.ch.]]则匹配于ch,但字母c或h则不是。[[=e=]]则能匹配各种语言里的e。
类别 匹配字符
[:alnum:] 数字字符
[:alpha:] 字母字符
[:blank:] 空格(space)与定位(tab)字符
[:cntrl:] 控制字符
[:digit:] 数字字符
[:graph:] 非空格字符
[:lower:] 小写字母字符
[:print:] 可显示的字符
[:punct:] 标点符号字符
[:space:] 空白(whitespace)字符
[:upper:] 大写字母字符
[:xdigit:] 十六进制数字
19 基本正则表达式BRE
BRE是由多个组成部分所构建,一开始提供数种匹配单个字符的方式,而后又结合额外的meta字符,进行多字符匹配
20 匹配单个字符
最先开始是匹配单个字符。可以采用集中方式做到:以一般字符,以转义的meta字符,以.(点好)meta字符,或是用方括号表达式:
一般字符:一般字指的是除特殊字符外的所有字符。一般字符就是表示它们自己,这种用法最直接也最容易理解。如shell匹配shell,WoRd匹配于WoRd,但不匹配于word。
特殊字符:特殊字符不能表示它们自己,当需要用特殊字符表示自己的时候,就需要用到转义字符\。\*匹配于字面上的* ,\\匹配于字面上的反斜杠\,\[ 匹配于左方括号。若将\放于一般字符前,这种情况会被忽视的。
.(点号): .点号字符即表示“任一字符”。a.c匹配于abc,aac,aqc 等等。单个点号用以表示自己的情况很少,它多半与其他meta字符搭配使用。
方括号表达方式[ ]:方括号表达式也是一种匹配单个字符的方式。最简单的方括号表达式是直接将字符列表放在方括号里,例如,[aeiouy]表示的就是所有小写元音字母。如:c[aeiouy]t匹配于cat,cot,cet,cyt,但不匹配cbt。方括号表达式里,^放在字首表示是取反的意思,也就是说,不在方括号列表里的任意字符。[^aeiouy]指的就是小写元音字符以外的任何字符,例如,大写元音字母,所有辅音字母,数字,标点符号等。c[^aeiouy]t则匹配cbt,cct,cAt,但不匹配cat,cet,cit,cot,cut,cyt。[0-9]表示[0123456789],[0-9a-fA-F]表示[0123456789abcdefABCDEF]
排序是指给予成组的项目排列顺序的操作。一个POSIX的排序元素由当前locale中的元素名称组成,并由[.与.]括起来。正则表达式[ab[.ch.]de]则匹配于字符a,b,d,e,或者是成对的ch。而单独的c或h字符则不匹配。
等价字符集用来让不同字符再匹配时视为相同字符。等价字符集将类别名称以[=与=]括起来。[a[=e=]iouy]就等同于所有小写英文字母元音,以及所有语言(英语,汉语,法语中的)e。
字符集它表示字符的类别,如数字,小写与大写字母,标点符号,空白等。这些类别名称定义于[:与:]之间。
在方括号表达式中,所有其他的meta字符都会失去其特殊含义。所以[*\.]匹配于字面上的星号,反斜杠以及点号。要让]也进入该集合,可以将它放在列表的最前面:[ ]*\.],这就能将]增加到列表中。要让减号-字符进入该集合,也需要将-减号放到最前端:[-*\.]。若要将 ] 和 - 都加入到该集合,则应该把 ] 放到最前面,而 - 放到最后面。如:[ ]*\.- ]
21 后向引用
BRE提供一种叫做后向引用的机制,指的是“匹配于正则表达式匹配的先前的部分”。使用后向引用的步骤有两个。第一步是将子表达式包围在\( 与\)里,单个模式里可包括至多9个子表达式,且可为嵌套结构。下一步是在同一模式之后使用\digit,digit指的是介于1至9的数字,指的是“匹配于第n个先前括号内子表达式匹配成功的字符”。例子:
模式 匹配成功
\(ab\)\(cd\)[def]*\2\1 abcdcdab,abcdeeecdab,abcdddeeffcdab 这里匹配是找到先以ab开头的字符串,然后接着是cd,然后[def]*,这个可能是没有,d,e,f,dd,ee,ff,ddd,eee,fff,....ddee,dddee,ddeee,ddfff,ddff,dff,df,de,ef,eeff,eeef,eeefff....很多,因为每次只能选d,e,f中的一个,然后根据后面的数字来匹配,\2,是[def]*匹配完了之后就要接着括号内的\(\)内的第二个表达式cd,\1接着就是第一个表达式ab。\(\)这里括号内的表达式是出现两次的。
\(why\).*\1 一行里重现两个why
\([[:alpha:]_])[[:alnum:]_] = \1; 简易的C/C++赋值语句
后向引用在寻找重复字以及匹配引号时特别好用:
\(["']\).*\1 匹配以单引号或双引号括起来的字,如'foo' 或 "bar" 这种情况下就无须担心时单引号还是双引号先找到
22 单个表达式匹配多字符
匹配多字符最简单的方法就是把它们一个接一个列出来,所以正则表达式ab匹配于ab,..(两个点号)匹配于任意两个字符,而[[:upper:]][[:lower:]]则匹配于任意一个大写字符,后面接着任意一个小写字符。ab*c表示的是"匹配1个a,0或多个b字符以及c"。ac abc abbc abbbc abbbbc
*修饰符时好用的,但没有限制,不能用*表示“匹配3个字符,而不是4个字符”,要使用一个复杂的方括号表达式,表明所需的匹配次数,但这很麻烦,可以用区间表达式来解决这类问题。区间表达式跟*一样,接在单个字符正则表达式后面,控制该字符连续重复几次即为匹配成功。区间表达式:
\{n\} 前置正则表达式所得结果重现n次
\{n,\} 前置正则表达式所得的结果重现至少n次
\{n,m\} 前置正则表达式所得到的结果重现n至m次
a\{5\}表示重现5个a,q\{10,42\}表示q出现10到42次
23 文本匹配锚点
^和$是锚点,其用途是限制正则表达式匹配时,针对要被匹配字符串的开始或结尾处进行匹配。假定现在有一串要进行匹配的字:abcABCdefDEF,看看下面的正则表达式是否匹配
模式 是否匹配 匹配成功/失败的原因
ABC 是 居中的第4 5及6个字符是ABC
^ABC 否 限定匹配字符串的起始处
def 是 居中的第7 8 及 9个字符是def
def$ 否 限制匹配字符串的结尾处
[[:upper:]]\{3\} 是 居中的第4,5,6个字符是大写字母
[[:upper:]]\{3\}$ 是 结尾的第10 11 及 12个字符是大写字母
^[[:alpha:]]\{3\} 是 起始的第1 2 3个字符是字母
^与$可以同时使用,这种情况是将括起来的正则表达式匹配整个字符串(或行)。有时^$这样的简易正则表达式也很好用,可以用来匹配空字符串或行列。
如: $cc -E foo.c | grep -v '^$' > foo.out 预先删除空行 grep -v 选项可以用来显示所有不匹配于模式的行
^与$仅在BRE的起始与结尾处具有特殊用途。在BRE下,ab^cd里的^表示的,就是自身^,同样地,ef$gh里的$在这里表示的也就是字面上的货币字符。
24 BRE运算符优先级
运算符优先级由高至低
运算符 表示意义
[..] [==] [::] 用于字符排序的方括号符号
\meta 转义字符\
[ ] 方括号表达式
\(\) \digit 子表达式与后向引用
* \{\} 前置单个字符重现的正则表达式
无符号 连续
^ $ 锚点
25 扩展正则表达式ERE
ERE拥有比基本正则表达式更多的功能。BRE与ERE在大多数meta字符与功能应用上几乎是完全一致。但也由区别。
匹配单个字符
匹配单个字符的情况下,ERE本质上与BRE一致,但有一个例外,这个例外出现在awk里,awk里的\符号在方括号表达式内表示其他的含义。因此,如果要匹配 [ - ] \ 需要用\进行转义。应该用 [\[\-\]\\ ]
ERE没有后向引用
匹配单个表达式与多个正则表达式
ERE在匹配多个字符这方面与BRE由明显的不同。*的处理上与BRE是相同的,区间表达式也可以用于ERE中,但它们是写在花括号里({}),且不需要前置反斜杠字符。a{5}表示重复出现5个a,q{10,42},重复出现10到42次q。ERE另由两个meta字符,可以更细腻地处理匹配控制:? 匹配于0个或一个前置正则表达式, + 匹配于1个或多个前置正则表达式。如:与ab?c匹配的有ac与abc,就这两个。ab+c匹配于abc,abbc,abbbc,abbbbbc,.....。
交替
方括号表达式易于表示“匹配于此字符,或其他字符,或...”,如[abc]匹配a,b或c。但不能指定"匹配于这个序列,或其他序列,或..."。要达到后者的目的,可以使用交替运算符 |。如:read|write匹配于read于write两者,fast|slow匹配于fast于slow两者。还可以使用多个该符号:sleep|doze|dream|nodoff|slumber 匹配5个表达式。
分组
圆括号((...))来提供分组功能。(why)+匹配于一个或连续重复的多个why。而why+ 匹配于why,whyy,whyyy,whyyyy,....等等。在必须用到交替时,分组的功能就特别好用。这可以用来构建复杂并较灵活的正则表达式。如[Tt]he (CPU|computer) is 指的就是:在The(或the)与is之间,含有CPU或computer的句子。圆括号在这里是特殊字符,而不是要匹配的输入文本。
将重复运算符与交替功能结合时,分组功能也是一定用得到的。read|write+ 指的是一个read,或是write后面接着任意个e字符。(read|write)+,指的是,有一个或重现多个read,或者一个或重现多个write。((read|write)[[:space:]]*)+ 的正则表达式看起来虽然比较复杂,不过由空白符,比较实际。
当用到交替操作结合^与$锚点字符使用时,分组就非常好用。交替 | 的运算优先级是最低的,正则表达式 ^abcd|efgh$ 的意思好似匹配字符串起始处是否由abcd,或者字符串结尾处是否由efgh。^(abcd|efgh)$表示的是找一个abcd或efgh的字符串。在ERE里,^与$永远都是特殊字符,所以,像ab^cd 与ef$gh这样的正则表达式仍是有效的,只是无法匹配到任何东西。它们在方括号里会失去特殊的意义
26 ERE运算符的优先级
优先级由高到低
运算符 含义
[..][==][::] 用于字符对应的方括号符号
\meta 转义字符\
[ ] 方括号表达式
() 分组
* + ? {} 重复前置的正则表达式
无符号 连续字符
^ $ 锚点
| 交替
2012年11月01日 星期四 21时32分20秒
正则表达式(二)
27 正则表达式的扩展
很多程序提供正则表达式语法扩展。这类扩展大多采取反斜杠加一个字符,以形成新的运算符。最常见的扩展为\<与\>运算符,分别匹配“单词(word)”的开头与结尾。单词是由字母.数字及下划线组成的,叫做单词组成。单词的开头要么出现在行起始处,要么出现在第一个后面紧跟一个非单词组成字符的单词组成字符。同样的,单词的结尾要么出现在一行的结尾处,要么出现在一个非单词组成字符之前的最后一个单词组成字符。如,正则表达式\<chop 匹配于 use chopsticks,但与eat a lambchop则不匹配。同样地,chop\>则匹配于第二个字符串,第一个则不匹配。注意,\<chop\>表达式与前两个字符串都不匹配。
额外的GNU正则表达式运算符
运算符 含义
\w 匹配任何单词组成字符,等同于[[:alnum:]]
\W 匹配任何非单词组成字符,等同于[^[:alnum:]]
\<\> 匹配单词的起始与结尾
\b 匹配单词的起始或结尾处所找到的空字符串。这与\<与\>运算符的结合。注意:由于awk使用\b 表示后退字符,因此GNU awk(gawk)使用\y表示此功能
\B 匹配两个单词组成字符之间的空子符传
\' \` 分别匹配emacs缓冲区的开始与结尾。GNU程序通常将它们视为与^及$同义
28 sed 流编辑器
sed流编辑器用来执行文本替换,sed的设计就是用来以批处理的方式而不是交互的方式来编辑文件。如果要做好几个变更,不管是对一个文件还是数个文件,比较简单的方式就是将这些变更部分写道一个编辑中的脚本里,再将此脚本应用到所有必须修改的文件。
29 sed基本用法
sed 's/:.*//' /xx/xx | sort -u 删除第一个冒号之后的所有东西并将结果进行排序并删除重复部分
sed 语法:sed [-n] 'editing command' [file ...]
sed [-n] -e 'editing command' ... [file ...]
sed [-n] -f script-file ... [file ...]
解释 -e 'editing command' 将editing command使用再输入数据上。当有多个命令需要应用时,就必须使用-e了。
-f script-file sed从script-file中读取编辑命令。当有多个命令需要执行时,此选项相当有用
-n 不是每个最后已修改结果行都正常打印,而是显示以p指定(处理过)的行。
sed 's/:.*//' /xx/xx | sort -u 这里的 's/:.*//' 就是editing-command