第3章 查找与替换——cut、join以及awk基础


0.sed补充:sed的d命令:
    sed '/^#/d' file    删除正则匹配的行
cut与join
cut
1.语法:
    cut -c list [file……]
    cut -f list [-d delim][file……]
    (1)-c list
        以字符为单位,执行剪下操作。list为字符编号或范围(以逗号隔开),如:1,3,5-12,42
    (2)-f list
        一字段为单位,执行剪下操作。list为字段编号或范围(以逗号隔开)。
    (3)-d delim
        使用delim作为定界符。默认定界符为制表符(Tab)
2.注意:
    (1)字符编号和字段编号都是从1开始
    (2)若处理的是字段,则定界符隔开的即为各字段,而输出时字段也以给定的定界符隔开。
    (3)若命令行没有指定文件,则读取stdin。
    (4)cut能识别宽字符,所以“字符”与“字节”意义不同。
join
3.作用:join命令将多个文件结合在一起,每个文件里的每条记录,都共享一个键值(key).
键值:指的是记录中的主字段。
4.插幅高清大图

第3章 查找与替换——sed基础(下)

1.sed匹配特定行:只要在命令前置一个地址,就可以限制一条命令应用到哪些行
address command
2.地址的种类:
(1)正则表达式
限制命令应用于匹配正则表达式模式的行。
可与s命令搭配使用:
‘/oldfunc/ s/$/# XXX: migrate to newfunc/’ 在行末加上注释
‘/bob/ s//& and tom/g’ 注意:s命令中的空模式指的是“使用前一个正则表达式”,所 以这个语句等同于/bob/ s/bob/& and tom/g
(2)最终行(。。不太理解~)
符号$指“最后一行”。          建议看这本书,比较经典《sed and awk》高清版下载链接
例:
sed -n ‘$p’ ‘$1′ 快速打印文件的最后一行
注意:“最后一行”指的是输入数据的最后一行,即最后一个文件的最后一行
(3)行编号
使用绝对的行编号作为地址(暂时了解不多)
(4)范围
可指定行的范围,仅需将地址以逗号隔开
例:sed -n ’10,42p’ foo.xml 仅打印10——42行
sed ‘/foo/,/bar/ s/baz/quux/g’ 仅替换范围内的行
注意:1)对于上述第二个例子,范围表达式的两项一定在不同行中,同一行中的前后两个项不构成匹配。
2)经测试,如果只找到范围表达式中的前一项,则实际范围为前一项所在行——最后一行;反之,如果只找到后一项,则没有行匹配。
3)经测试,如果范围表达式中的后一项有多个,则匹配最先找到的那个;如果范围表达式的前一项有多个,也是匹配最先找到的那个。
4)经测试,如果范围表达式中的后一项在前面行,而前一项在后面行,则结果有点乱。。不分析,我认为应该尽量避免这种情况。

第3章 查找与替换——sed基础(上)

最近真是有够忙的,不过仔细想想自己其实一直处在这种状态中,,,各种东西要去学。走在路上脑中一会儿跳出个nesC,一会儿想起某个数据结构题,想着想着又会出现个在线雇佣问题k的计算。。然后到了吃饭的时候,又该想想java的多态和c++的对比以及shell的那几个易忘点。总之,生活越来越快节奏了,唯一能应对的办法只有更拼了。。
好吧,该做的还是得做。复习下sed基础,记下笔记。。
1.语法:

第3章 查找与替换——(POSIX)ERE正则表达式

1.关于反斜杠:ERE中,\无论在哪,都表示转义,要表示\,需使用\\
2.ERE中没有后向引用
3.区间表达式:{} 与BRE的区别是没有反斜杠。
注意:如果{没有匹配的},则定义为”未定义状态“
4.? 匹配0个或1个前置正则表达式
5.+ 匹配1个或多个前置正则表达式
6.交替运算符(管道运算符)| :方括号表达式可以表示”匹配这个字符,或是那个字符……“,而交替运算符可以表示”匹配这个序列,或是那个序列,或是……“。
例如:read|write|see匹配read或write或see。|在ERE中优先级最低。
7.分组()
ERE运算符被应用到”前置正则表达式“。()运算符正是提供了”前置“的范围。
例如:(why)+ 匹配一个或连续的多个why
((read|write)[[:space:]]*)+ 匹配多个(包括一个)连续出现的read或write,且中间可能被空白隔开。
8.注意^abcd|efgh$和^(abcd|efgh)$的不同
前者:匹配起始处为abcd或结尾处为efgh的字符串行
后者:匹配正是abcd或正是efgh的字符串行
原因:|的优先级最低
9.ERE运算符的优先级

10.额外的GNU正则表达式运算符

11.unix程序及其正则表达式类型

12.grep默认使用BRE,加上-E选项则使用ERE。
13.通常,awk在其ERE中不支持区间表达式,为了可移植性,应当使用反斜杠转义{}。

第3章 查找与替换——(POSIX)BRE正则表达式

1.grep的用法:
-E 使用扩展正则表达式进行匹配。
-F 使用固定字符串进行匹配,可省略
-e 字符串以减号开头时grep会混淆。-e可以指定其参数为模式(字符串)
-f pat-file 从pat-file文件读取模式作匹配
-i 模式匹配时忽略字母大小写差异
-l 列出匹配模式的文件名称,而不是对应的行
-q 静默的。grep成功则离开,而不是写入stdin。
-s 不显示错误信息。通常与-q并用。
-v 取反,显示不匹配的行
2.(POSIX)正则表达式
(1)特殊字符常称为元字符(meta字符)
(2)POSIX BRE与ERE的meta字符



(3)方括号表达式:
1》字符集 [::]括起来,如英文字符[[:alpha:]]
2》排序符号 [..]括起来 如[[.ch.]],匹配ch,而不匹配单个c或h
3》等价字符集 [==]括起来 如[[=e=]],在法文locale里,可能匹配于e、é、è等
注意:以上三种构造必须在方括号表达式中

3.基本正则表达式(BRE)
(1)匹配单个字符
1》如何让meta字符表示他们自己?
答:前面加上反斜杠\转义:如\*匹配*,\\匹配\
2》. 匹配“任一字符”。
3》用方括号表达式可以匹配单个字符
注意一:在方括号表达式里,^放在字首表示取反,也就是匹配不在方括号列表里的任意字符。如[^aeiou]匹配除小写元音以外的字符。
注意二:方括号表达式允许“范围”,如[0-9]表示0123456789、[0-9a-z]等
这里有个问题:这样做可能降低移植性,因为这里的范围与locale相关(locale排序序列里的位置,你系统上的[0-a]和他系统上的[0-a]可能包括不一样的字符)
4》方括号表达式的注意点:
<1>在方括号表达式中,其他的meta字符都会失去特殊含义。
<2>如何让]进入该集合?
答:将]放到列表的最前面
如何让-进入该集合?
答:将-放到列表的最前面
如何让]和-都进入该集合?
答:将]放到第一个字符,将-放到最后一个字符
(2)后向引用
第一步:将子表达式包围在\(与\)里。可嵌套。
第二步:在同一模式之后使用\digit。digit范围1——9。、
意义:指的是“匹配于第n个先前方括号内子表达式匹配成功的字符”
如何确定子表达式的编号,以左括号为准,从左至右依次为1——9
例:\(['"]\).*\1 匹配以单引号或双引号括起来的字。当前面匹配成功的是’时,后面必须出现’才算匹配。前面是”时,同。
(3)*和\{ \}
*:表示前面的正则表达式重复出现任意次(包括0次)
如ab*c匹配:ac abc abbc 但是不匹配aQc
注意:在BRE中,*在最前面表示其本身,失去特殊意义
\{和\}:
1》\{n\} 前置正则表达式所得结果出现n次
2》\{n,\} 前置正则表达式所得结果至少出现n次
3》\{n,m\} 前置正则表达式所得结果出现次数>=n次,<=m次
n与m的值必须介于0至RE_DUP_MAX(含)之间。
RE_DUP_MAX:POSIX定义的符号常量,可用getconf取得。
注意:以上两个meta符只能作用于单个字符正则表达式
(4)文本匹配描点
^和$称为描点
^ 表示其后的正则表达式出现在行开头
$ 表示其后的正则表达式出现在行结束
如^$表示空行
注意:^和$只有在BRE的起始和结尾处才有特殊用途。
(5)BRE运算符优先级:

shell编程笔记(第二章-入门)

0.一些容易忘记的小知识点:
ctrl+D        end of file
ctrl+z        stop一个程序
jobs        查看目前系统中stop的程序
fg 序号        将一个stop的程序调到前台继续执行
stty -echo    关闭自动打印输入字符
stty echo    打开自动打印输入字符
$?            这个变量保存上一条命令的返回值,成功一般为0
read        从stdin读入数据保存到变量
who            当前系统中的用户
grep 关键词 grep的最简单用法,找到含有关键词的那些行并显示
.profile    开机时会读取该文件并执行其中的命令。
1.关于第一行#!
#! /bin/sh -
这一行用于告诉内核用哪个解释程序来运行,可以是shell,也可以是其他程序如awk。
参数-表示没有选项,这是基于安全考虑,避免欺骗式攻击。
2.shell可以执行的命令:内建命令、shell函数、外部命令
外部命令的执行:

3.关于shell变量
(1)变量以字母或下划线开始
(2)变量赋值:变量名=变量值
注意:1)如果变量值之间有空格,要加双引号:name=”shadow xuhao”
2)单行可以给多个变量赋值:firstname=hao lastname=xu
3)访问变量的值需要在变量名前加$:echo $name
4)变量合并时,若变量间有空格,则需要加双引号:newname=”$firstname $lastname”
4.echo命令:
echo会解释转义字符
\a    警示字符,通常是ASCII的BEL字符
\b    退格
\c    输出中忽略最后的换行字符。这个参数之后的任何字符,包括接下来的参数,都会被忽略(不打印)
\f    清屏
\n    换行
\r    回车
\t    水平制表符
\v    垂直制表符
\\    反斜杆
\0ddd    将字符表示成1到3位的八进制数值
5.printf命令:
注意:用法基本和C语言中相同,当参数个数多于占位符个数时会循环使用占位符。

6.基本的I/O重定向:
(1)默认的标准输入、标准输出、标准错误输出都是终端
(2)重定向与管道
1)改变默认I/O的来源端和目的端
program < file    将program的标准输入改为file
program > file    将program的标准输出改为file
2)重定向符>在目标文件不存在时会新建一个,若文件已存在则会覆盖。
3)》会将数据附加到目标文件
(3)tr命令:
tr [options] source-char-list replace-char-list
作用:转换字符
常用选项:
-c    取source-char-list的反义,要转换的字符为未列在source-char-list中的字符
-C    与-c相似,但所处理的是字符(可能是宽字符),而非二进制的字节值
-d    删除所列的字符
-s    浓缩重复的字符。如果标准输入中连续重复出现source-char-list里所列的字符,则浓缩成一个。
(4)两个特殊文件/dev/null  /dev/tty
1)/dev/null    (bit bucket位桶)
这个文件相当于windows中的回收站
2)/dev/tty
当程序打开此文件时会自动重定向到一个终端
7.基本命令查找
(1)shell根据PATH的先后顺序依次查找相关目录
(2)空项目:表示当前目录。
在最前:    :/bin:/root/bin
在最后:    /bin:/root/bin:
在中间:    /bin::/root/bin
注意:事实上不应该把空项目写入PATH,会引起安全问题
8.简单的执行跟踪
set -x        打开执行跟踪
set +x        关闭执行跟踪
9.国际化(i18n)与本地化(l10n):
(1)用来控制让哪种语言或文化环境生效的功能就叫做locale
(2)各种locale环境变量

shell编程基础(总体轮廓)

0.关于shell编程
大一学shell编程的时候没有时间深入,而且不做笔记,只是看看,这样很不好,过没几天就忘了,等于没学。这段时间一直在学曾经中断了的算法,但是从早到晚一直看这个也不行。感觉强度有点高,所以决定利用时间间隙把shell编程认真学一遍。就当做是放松大脑吧。
1.如何让写好的shell脚本运行?
答:chmod +x 文件名    或    .文件名。为了方便,可以把脚本文件所在目录加入PATH.PATH=$PATH:文件完整路径
另一个运行脚本的方法:把它作为一个参数传给bash命令。bash 文件名
2.shell脚本的参数
(1)位置参数:$N    N为自然数。$0是程序名字,$1是第一个参数
(2)内部参数:
$0:程序名
$#:参数总数目
$?:上一个代码或shell程序的返回值。正常返回0.
$*:所有参数组成的字符串(不包括$0,所有指的是从$1开始的参数)
3.test命令:
(1)字符串比较:
=    比较字符串是否相同,相同为‘是’
!=    不同为‘是’
-n    字符串长度大于0,则为‘是’
-z    字符串长度等于0,则为‘是’
(2)数字比较
-eq        相等
-qe        大于等于
-le        小于等于
-ne        不相等
-gt        大于
-lt        小于
(3)逻辑操作
!    逻辑取反
-a    逻辑与
-o    逻辑或
(4)文件操作

关于linux的参数执行顺序。。

        今天在看正则表达式的时候遇到了两个问题,用vi打开/etc下的sysctl.conf的时候会发现有许多空白行和注释行。但是有时候stdout的时 候并不需要这些信息,若是打印时则更能节省纸张资源。-_-!于是我用grep命令将其去除,具体指令为grep -v ‘^$’ /etc/sysctl.conf|grep -v ‘^#’可是运行完该句之后的结果着实让我头疼,因为我发现注释行仍然出现了,而且前面还多了一个数字。往上一检查才发现自己多打了一个n。。命令变成了 grep -vn ‘^$’ /etc/sysctl.conf|grep -v ‘^#’。
        这对我来说是个不错的收获。因为大家都知道管道命令会把前者的stdout转换为后者的stdin,而碰巧的是n正好有是grep的一个参数,用于输出行 号。于是后者的stdin的每行的开始都有了行号。这样每行的开始都不是#字符了,注释也就自然没被去除。看来管理时真的要小心谨慎,一不小心结果就会发 生错误。另外,如果有些童鞋在不是自己的主机上执行该命令的时候会发现命令完全正确,可是结果还是有类似错误。这时候很可能是因为grep被该用户 alias过的原因。比如该用户alias grep=’grep -v’.这样会有更奇怪的结果哦(会有两列行号^_^)当然这点如果多执行命令的话也是可以发现的,其实type grep一下就·ok。而且一般人不会这么做,毕竟v用于显示没有指定字符串的行。如果真是这个原因,怎么改呢?很简单,去改下用户目录下 的.bashrc文件吧。这个是login shell会读取的文件。里面会初始化一些命令别名,然后会注册一些环境变量。login时会被~/.bash_profile调用。如果发现grep被 alias成带v参数,就赶紧把它注释掉吧。要想立刻生效的话,手动读取一下吧。source ~/.bashrc 这样就ok了。
这时候,,又想到一个问题,上述命令中的参数v和n是哪个先执行呢。联系到最近在win32汇编上学的c调用、stdcall都是右边参数先入栈来看的 话,我想linux应该也类似吧(。。。纯属个人胡扯~~~~)。那样应该是自左向右顺序执行的。从结果来看,空行确实被去除了,那是不是真的是自左向右 的顺序呢。于是验证了一下。grep -nv ‘^$’ /etc/sysctl.conf|grep -v ‘^#’结果空行还是被去除了。看来假设不对。如果自左向右,那么-n执行后每行都有行号,再执行-v不会去除空行。当然这里有个问题,那就是我不清楚第 一个参数执行后是否真正影响了输出,如果行号没被算进去的话执行-v后还是会去除空行的。这样参数执行顺序的问题还是不敢下定论。。可是大年夜的没有网络 可用。看来有机会得去百度一下了。。
不过,这时候,,,天亮了。。下午四五点起床的孩子通宵无压力。。O~睡觉去了。。。
以上分析纯属本人臆测,OS为Cent OS。内核为2.6.32-71.e16.i686。不过我开了下gentoo,发现gentoo的用户~目录下好像没有.bashrc文件、、、
(以上均为本人学习过程中的杂乱思绪,不免大量错误,不做任何参考。。)