2011年12月22日星期四

《Classic Shell Scripting》:sort,uniq,wc,head,tail

一.sort
就像awk,cut与join一样,sort将输入看作具有多条记录的数据流,而记录是由可变宽度的字段组成,记录是以换行符作为定界符,字段的定界符则是空白字符或是用户指定的单个字符。

“
语法
   sort [ options ] [ file(s)]
用途
   将输入行按照键值字段与数据类型选项以及locale排序
主要选项
   -b : 忽略开头的空白
   -c : 检查输入是否已正确地排序。如输入未经排序,但退出码(exit code)为非零值,则不会有任何输出
   -d : 字典顺序,仅文字数字与空白才有意义
   -g : 一般数值,以浮点数字类型比较字段
   -f : 将混用的字母都看作相同大小写,也就是以不管字母大小写的方式排序。
   -i : 忽略无法打印的字符
   -k : 定义排序键值字段
   -m : 将已排序的输入文件,合并为一个排序后的输出数据流
   -n : 以整数类型比较字段
   -o outfile : 将输出写到指定的文件,而非标准输出。如果该文件为输入文件之一,则sort在进行排序与写到输出文件之前,会先将它复制到一个临时的文件。
   -r : 倒置排序的顺序为由大到小,而非默认的由小到大。
   -t char : 使用单个字符char作为默认的字段分隔字符,取代默认的空白字符
   -u : 只有惟一的记录:丢弃所有具有相同键值的记录,只留其中的第一条。只有键值字段是重要的,也就是说,被丢弃的记录其他部分可能是不同值。
行为模式
   sort会读取指定的文件,如果未给定文件,则读取标准输入,再将排序好的数据写至标准输出。
”
举例如下:
sort -t: -k1,1 /etc/passwd    #以用户名称排序
sort -t: -k3nr /etc/passwd    #反向UID的排序
sort -t: -k4n -k3n /etc/passwd   #先以GID排序,再以UID排序

sort排序算法并不稳定,幸好GNU实现了coreutils弥补不足,它可以通过--stable选项补救此问题。

二.uniq
uniq常用于管道中,用来删除已使用sort排序完成的重复记录:sort ... | uniq | ...
范例:
sort latin-numbers | uniq     #显示唯一的,排序后的记录,重复则仅取唯一行。
sort latin-numbers | uniq -c  #计数唯一的,排序后的记录
sort latin-numbers | uniq -d  #仅显示重复的记录
sort latin-numbers | uniq -u  #仅显示未重复的记录

三.wc
echo Testing one two three | wc -c  #计算字节数
echo Testing one two three | wc -l  #计算行数
echo Testing one two three | wc -w  #计算字数/单词数

-c选项原本是表示字符数,但因为有多字节字符集的编码存在---像UTF-8,因此在当前系统上,字节数已不再等于字符数了,也因此,POSIX出现了-m选项,用以计算多字节字符,对8位字符数据而言,它等同于-c。

虽然wc最常处理的是来自于管道的输入数据,但它也接受命令行的文件参数,可以生成一行一个结果: wc /etc/passwd /etc/group

四.head and tail
有时,你会需要从文本文件里把几行字---多半是靠近开头或结尾的几行,提取出来。
head [-n] n [ file(s) ]    #取出文件的前n行
同样功能的命令有:
awk 'FNR <= n' [ file(s) ]
sed [-e] nq    [ file(s) ]

tail [-n] n [ file(s) ]   #取出文件的后n行

《Classic Shell Scripting》:sed and cut

一. sed
一般来说,执行文本替换的正确程序应该是sed --- 流编辑器(Stream Editor)。sed的设计就是用来以批处理的方式而不是交互的方式来编辑文件。当你知道要做好几个变更 --- 不管是对一个还是数个文件时,比较简单的方式是将这些变更部分写到一个编辑中的脚本里,再将此脚本应用到所有需要修改的文件。
你可能会常在管道中间使用sed,以执行替换操作。做法是使用s命令 --- 要求正则表达式寻找,用替代文本替换匹配的文本:
sed 's/:.*//' /etc/passwd |       #删除第一个冒号之后的所有东西
 sort -u                          #排序列表并删除重复部分

在这里,/字符扮演定界符(delimiter)的角色,从而分隔正则表达式与替代文本。在本例中,替代文本是空的,实际上会有效地删除匹配的文本。虽然/是最常用的定界符,但任何可显示的字符都能作为定界符。在处理文件名称,通常都会以标点符号字符作为定界符(例如分号,冒号或逗点):
find /home/tolstoy -type d -print |   #寻找所有目录
sed 's;/home/tolstoy/;/home/lt/;' |   #修改名称;
sed 's/^/mkdir /' |                   #插入mkdir命令
sh -x                                 #以Shell跟踪模式执行

“
语法
    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 : 自script-file中读取编辑命令。当有多个命令需要执行时,此选项相当有用。
    -n : 不是每个最后已修改结果行都正常打印,而是显示以p指定(处理过)的行。
行为模式
    读取每个输入文件的每一行,假如没有文件的话,则是标准输入。以每一行来说,sed会执行每一个应用到输入行的editing command。结果会写到标准输出(默认状态下,或是显示地使用p命令及-n选项)。若无-e或-f选项,则sed会把第一个参数看作是要使用的editing command。
”
二.cut
cut命令是用来剪下文本文件里的数据,文本文件可以是字段类型或是字符类型。后一种数据类型在遇到需要从文件里剪下特定的列时,特别方便。请注意:一个制表符在此被视为单个字符。
举例来说,下面的命令可显示系统上每个用户的登录名称及其全名:
cut -d : -f 1,5 /etc/passwd     #取出字段
下面的命令取出命令ls -l的输出结果中的文件权限字段:
ls -l | cut -c 1-10

"
语法
   cut -c list [ file ...]
   cut -f list [ -d delim ] [ file ...]
用途
   从输入文件中选择一个或多个字段或者一组字符,配合管道,可再做进一步处理。
主要选项
   -c list : 以字符为主,执行剪下的操作。list为字符编号或一段范围的列表(以逗点隔开),例如1,3,5-12,42。
   -d delim : 通过-f选项,使用delim作为定界符。默认的定界符为制表字符(Tab)
   -f list : 以字段为主,做剪下操作。list为字段编号或一段范围的列表(以逗点隔开)
"

2011年12月9日星期五

《Class Shell Scripting》第一,二章读书笔记

第一章:背景知识
1.软件工具的原则
一次做好一件事
处理文本行,不要处理二进制数据
使用正则表达式:正则表达式(regular expression)是很强的文本处理机制。了解它的运作模式并加以使用,可适度简化编写命令脚本的工作。
默认使用标准输入/输出:在未明确指定文件名的情况下,程序默认会从它的标准输入读取数据,将数据写到它的标准输出,至于错误信息则会传送到标准错误输出。以这样的方式来编写程序,可以轻松地让它们称为数据过滤器(filter)。
避免喋喋不休
输出格式必须与可接受的输入格式一致:专业的工具程序认为遵循某种格式的输入数据,例如标题行之后接着数据行,或在行上使用某种字段分隔符等,所产生的输出也应遵循与输入一致的规则。这么做的好处是,容易将一个程序的执行结果交给另一个程序处理。
让工具去做困难的部分:虽然UNIX程序并非完全符合你的需求,但是现有的工具或许已经可以为你完成90%的工作。接下来,若有需要,你可以编写一个功能特定的小型程序来完成剩下的工作。
构建特定工具前,先想想:你所要做的事情,是否有其他人也需要做?这个特殊的工作是否有可能是某个一般问题的一个特例?如果是的话,请针对一般问题来编写程序。

第二章:入门
1.Shell脚本最常用于系统管理工作,或是用于结合现有的程序以完成小型的,特定的工作。一旦你找出完成工作的方法,可以把用到的命令串在一起,放进一个独立的程序或脚本里,此后只要直接执行该程序便能完成工作。

2.使用脚本编程语言的好处是,它们多半运行在比编译型语言还高的层级,能够轻易处理文件与目录之类的对象。缺点是:它们的效率通常不如编译型语言。

3.Shell的基本元素:
1).命令与参数
2).变量
3).简单的echo输出
4).华丽的printf输出
5).基本的I/O重定向
(1)重定向与管道
(2)特殊文件:/dev/null与/dev/tty
6).基本命令查找

4.命令行中,分号(;)可用来分隔同一行里的多条命令。Shell会依次执行这些命令。

5.Shell识别三种命令:内建命令,Shell函数以及外部命令:
1).内建命令就是由Shell本身所执行的命令。有些命令是由于其必要性才内建的,例如cd用来改变目录,read会将来自用户(或文件)的输入数据传给Shell变量。另一种内建命令的存在则是为了效率,其中最典型的就是test命令,编写脚本时会经常用到它。另外还有I/O命令,例如echo与printf。
2).Shell函数是功能健全的一系列程序代码,以Shell语言写成,它们可以像命令那样引用。 ???
3).外部命令就是由Shell的副本(新的进程)所执行的命令,基本的过程如下:
a. 建立一个新的进程。此进程即为Shell的一个副本。
b. 在新的进程里,在PATH变量内所列出的目录中,寻找特定的命令。
c. 在新的进程里,以所找到的新程序取代执行中的Shell程序并执行。
d. 程序完成后,最初的Shell会接着从终端读取下一条命令,或执行脚本里的下一条命令。

6.Shell变量名称的开头是一个字母或下划线符号,后面可以接着任意长度的字母,数字或下划线符号。

7.重定向与管道:
以<改变标准输入
以>改变标准输出,>重定向符(redirector)在目的文件不存在时,会新建一个。然而,如果目的文件存在,它就会直接覆盖掉,原本的数据都会丢失
以>>改变标准输出附加到文件,如同>,如果目的文件不存在,>>重定向符便会新建一个。然而,如果目的文件存在,它不会直接覆盖掉文件,而是将程序产生的数据附加到文件结尾处。
以|建立管道,管道可以使得执行速度比使用临时文件快上十倍。

8.tr命令

9.构造管道时,应该试着让每个阶段的数据量变得更少。换句话说,如果你有两个要完成的步骤与先后次序无关,你可以把会让数据量变少的那一个步骤放在管道的前面。这么做可以提升脚本的整体性能,因为UNIX只需要在两个程序间移动少的数据量,每个程序要做的事情也比较少,例如:使用sort排序之前,先以grep找出相关的行,这样可以让sort少做些事。

10.特殊文件/dev/null与/dev/tty

11.简单的执行跟踪:
两种方法:1.使用"sh -x scriptname"来执行脚本scriptname;2.在脚本中需要跟踪的命令片段前加一句set -x打开执行跟踪的功能,然后在这个命令片段后再用set +x命令关闭它。

2011年12月7日星期三

Linux添加定时执行任务

在Linux下如果希望某个任务定时地执行,一般是使用cron服务器,将任务添加到cron任务列表中。
1.启动,关闭,重启cron(需超级用户权限):
/etc/init.d/cron start
/etc/init.d/cron stop
/etc/init.d/cron restart
注:archlinux下为/etc/rc.d/crond start|stop|restart
2.查看用户设置的定时任务列表:
crontab [-u xxx] -l       #  xxx为用户名
3.编辑用户的定时任务列表(超级用户权限):
crontab -u xxx -e
4.删除用户的定时任务列表(超级用户权限):
crontab -u xxx -r
5.定时任务的编辑规则:
cron的定时任务由两部分组成:(1)设置的时间(2)该时间下要执行的任务命令。
时间分5个部分,依次为:
minute             0-59
hour                0-23 
day of month   1-31
month             1-12
day of week     0-7 (0 or 7 is Sun, or use names)
示例(每天临晨2点备份数据库):
0 2 * * * mysqldump -hhostname -uusername -ppassword databasename > backupfile.sql
6.使设置生效

Linux添加sudo用户

Linux中很多命令需要使用超级用户权限,在这些命令前添加sudo然后直接执行是很方便的。

那么就先要将自己的用户名添加到sudoers中:
1.使用su命令切换到超级用户(在提示后输入root的密码)
2.使用visudo命令(编辑/etc/sudoers文件),也可以直接使用编辑器编辑。
3.找到root ALL=(ALL) ALL 这一行,在其下面一行添加xxx ALL=(ALL) ALL,其中xxx为你的用户名。
4.保存即可起效。

2011年12月6日星期二

wget 使用技巧

By linuxtoy.org

wget 是一个命令行的下载工具。对于我们这些 Linux 用户来说,几乎每天都在使用它。下面为大家介绍几个有用的 wget 小技巧,可以让你更加高效而灵活的使用 wget。
  • $ wget -r -np -nd http://example.com/packages/
这条命令可以下载 http://example.com 网站上 packages 目录中的所有文件。其中,-np 的作用是不遍历父目录,-nd 表示不在本机重新创建目录结构。
  • $ wget -r -np -nd --accept=iso http://example.com/centos-5/i386/
与上一条命令相似,但多加了一个 --accept=iso 选项,这指示 wget 仅下载 i386 目录中所有扩展名为 iso 的文件。你也可以指定多个扩展名,只需用逗号分隔即可。
  • $ wget -i filename.txt
此命令常用于批量下载的情形,把所有需要下载文件的地址放到 filename.txt 中,然后 wget 就会自动为你下载所有文件了。
  • $ wget -c http://example.com/really-big-file.iso
这里所指定的 -c 选项的作用为断点续传。
  • $ wget -m -k (-H) http://www.example.com/
该命令可用来镜像一个网站,wget 将对链接进行转换。如果网站中的图像是放在另外的站点,那么可以使用 -H 选项。

Linux内核设计与实现-进程管理部分笔记