标签 shell 下的文章

[Apache]访问日志IP统计

这两个服务器apache error日志暴涨~~~,检查了下日志,封了几个IP

日志内容如图~~~

 

QQ20141206-1

cat ip-error.log |awk -F " " '{print $8}'|sed 's/]//g'|sort|uniq -c|sort -rn

首先用awk 过滤出IP. 以空格位分隔符,打印第八个域,然后用sed 把多余出来的]替换,再排序统计,最后输出到一个文件

得到如图锁所示IP,然后检查量比较大的IP,封了有问题的就OK

iptables -I INPUT -s ip -j DROP

 

QQ20141206-2.

Linux 删除指定日期之前的文件

要删除系统中就的备份文件,就需要使用命令了:

#find /tmp -mtime +30 -type f -name *.sh[ab] -exec rm -f {} ;

 

假如在一个目录中保留最近30天的文件,30天前的文件自动删除

#find /tmp -mtime +30 -type f -name *.sh[ab] -exec rm -f {} ;

 

/tmp –设置查找的目录;

-mtime +30 –设置时间为30天前;

-type f –设置查找的类型为文件;

-name *.sh[ab] –设置文件名称中包含sha或者shb;

-exec rm -f –查找完毕后执行删除操作;

提示:将此命令写入crontab后即可自动完成查找并删除的工作

另外的方法大同小异

#find . -mtime +30 -type f | xargs rm -rf

 

我的操作是:先ls -ltr 查看时间,没有太久的所以就用 -cmin n查找系统中最后N分钟被改变文件状态的文件。具体命令:

$ find /home/oracle/test6 -cmin +20 -type f -name *.xml -exec rm -f { } ;

 

另外的方法大同小异

#find . -mtime +30 -type f | xargs rm -rf

$find . -type f -cmin +10 -exec rm -rf *.xml {} ;

find . type f -name "debug*" -atime +3 -exec rm -f {} ;

 

首先cd进入目录:

find . -name "*~" -exec rm {} ;

find . -ctime +n -exec -exec rm -vi {} ;

 

这里的+n是指多少天以前,比如:+7

find . -ctime +7 -exec -exec rm -vi {} ;

 

如果不想手动确认,把命令中的-vi改成-fv

请详查find命令。

使用find时要区分清楚atime,ctime,mtime的区别,一般都使用mtime来查找,因为在ls -al显示出来的就是mtime时间戳,可以使用:

# find $PAHT -mtime +3 -ok rm {} ;

 

在交互模式下删除比较保险。

一、按照一定日期格式命名文件

1、按照一定的格式输出日期:

date +”%y%m%d”

格式说明:

% : 印出 %

%n : 下一行

%t : 跳格

%H : 小时(00-23)

%I : 小时(01-12)

%k : 小时(0-23)

%l : 小时(1-12)

%M : 分钟(00-59)

%p : 显示本地 AM 或 PM

%r : 直接显示时间 (12 小时制,格式为 hh:mm:ss [AP]M)

%s : 从 1970 年 1 月 1 日 00:00:00 UTC 到目前为止的秒数

%S : 秒(00-60)

%T : 直接显示时间 (24 小时制)

%X : 相当于 %H:%M:%S

%Z : 显示时区

日期方面 :

%a : 星期几 (Sun-Sat)

%A : 星期几 (Sunday-Saturday)

%b : 月份 (Jan-Dec)

%B : 月份 (January-December)

%c : 直接显示日期与时间

%d : 日 (01-31)

%D : 直接显示日期 (mm/dd/yy)

%h : 同 %b

%j : 一年中的第几天 (001-366)

%m : 月份 (01-12)

%U : 一年中的第几周 (00-53) (以 Sunday 为一周的第一天的情形)

%w : 一周中的第几天 (0-6)

%W : 一年中的第几周 (00-53) (以 Monday 为一周的第一天的情形)

%x : 直接显示日期 (mm/dd/yy)

%y : 年份的最后两位数字 (00.99)

%Y : 完整年份 (0000-9999)

2、命名带有日期的文件:filename`date +%y%m%d`,此处的”`”不是单引号。

二、以创建文件日期为界线删除文件

1、find命令简解

find pathname -options [-print -exec -ok …]

 

pathname: find命令所查找的目录路径。例如用。来表示当前目录,用/来表示系统根目录。

-print: find命令将匹配的文件输出到标准输出。

-exec: find命令对匹配的文件执行该参数所给出的shell命令。相应命令的形式为’command’ { } ;,注意{ }和;之间的空格。

-ok: 和-exec的作用相同,只不过以一种更为安全的模式来执行该参数所给出的shell命令,在执行每一个命令之前,都会给出提示,让用户来确定是否执行。

options:

-name

按照文件名查找文件。

-perm

按照文件权限来查找文件。

-prune

使用这一选项可以使find命令不在当前指定的目录中查找,如果同时使用-depth选项,那么-prune将被find命令忽略。

-user

按照文件属主来查找文件。

-group

按照文件所属的组来查找文件。

-mtime -n +n

按照文件的更改时间来查找文件, – n表示文件更改时间距现在n天以内,+ n表示文件更改时间距现在n天以前。find命令还有-atime和-ctime 选项,但它们都和-m time选项。

-nogroup

查找无有效所属组的文件,即该文件所属的组在/etc/groups中不存在。

-nouser

查找无有效属主的文件,即该文件的属主在/etc/passwd中不存在。

-newer file1 ! file2

查找更改时间比文件file1新但比文件file2旧的文件。

-type

查找某一类型的文件,诸如:

b – 块设备文件。

d – 目录。

c – 字符设备文件。

p – 管道文件。

l – 符号链接文件。

f – 普通文件。

-size n:[c] 查找文件长度为n块的文件,带有c时表示文件长度以字节计。

-depth:在查找文件时,首先查找当前目录中的文件,然后再在其子目录中查找。

-fstype:查找位于某一类型文件系统中的文件,这些文件系统类型通常可以在配置文件/etc/fstab中找到,该配置文件中包含了本系统中有关文件系统的信息。

-mount:在查找文件时不跨越文件系统mount点。

-follow:如果find命令遇到符号链接文件,就跟踪至链接所指向的文件。

-cpio:对匹配的文件使用cpio命令,将这些文件备份到磁带设备中。

对于时间相关的参数,有以下补充:

-amin n

查找系统中最后N分钟访问的文件

-atime n

查找系统中最后n*24小时访问的文件

-cmin n

查找系统中最后N分钟被改变文件状态的文件

-ctime n

查找系统中最后n*24小时被改变文件状态的文件

-mmin n

查找系统中最后N分钟被改变文件数据的文件

-mtime n

查找系统中最后n*24小时被改变文件数据的文件

2、删除固定日期以前的文件

find logs -type f -mtime +5 -exec rm { } ;

 

Shell快捷键

转自:www.gaobiao.org

Ctrl + a 可以快速切换到命令行开始处。
Ctrl + e 切换到命令行末尾
Ctrl + r 在历史命令中查找
Ctrl + u 删除光标所在位置之前的所有字符
Ctrl + k 删除光标所在位置之后的所有字符
Ctrl + c 终止命令
Ctrl + d 结束当前输入、退出shell
Ctrl + z 转入后台运行
ctrl + s 刷屏信息过快,可用来停留在当前屏
ctrl + q 恢复刷屏
ctrl + 左右方向,在命令行按词为单位进行移动
ctrl + w 删除光标之前的一个单词
ctrl + l 清屏,clear

日志自动备份脚本(基于rsyslog)

#!/bin/bash
service rsyslog stop
BackupPath=/Logback/
LogFile=/Logback/back.log
DBPath=/var/log/switch
Date=$(date +%y%m%d)
File=/Logback/log_bak$Date.tgz
NewFile=”$BackupPath”log_bak$Date.tgz
if [ ! -d “$BackupPath” ]; then
mkdir $BackupPath
fi
echo “——————————————-” >> $LogFile
echo $(date +”%y-%m-%d %H:%M:%S”) >> $LogFile
echo “————————–” >> $LogFile
tar cPzvf $NewFile $DBPath >> $LogFile 2>&1
if [ -f “$File” ]; then
rm -rf /var/log/switch/*
else
echo “文件不存在,现在开始备份!” >> $LogFile
tar cPzvf $NewFile $DBPath >> $LogFile
fi
echo “日志备份成功!” >> $LogFile
service rsyslog start
chmod -R 755 /var/log/switch/
echo “注意:备份文件解压路径为’/var/log/switch/ ‘,解压时注意防止覆盖未备份日志文件!” >> $LogFile
mail -s “日志备份成功!” liufengnian@ghnovo.com < /Logback/back.log

详解著名的awk oneliner

Awk onel iner 文档 版权归原作者及译者所有,仅供阅读,交流!

详解著名的awk oneliner

Part 1:空行、行号和计算
偶然在网上看到有人注释过的《awk oneliner》,而且注释的人声称“全部弄懂这 些就已经是awk高手了”,而我也一直想学下awk又懒得花时间,然后就觉得这个东 西一定很适合我。为了督促自己看完这个系列,决定整个给翻译一遍。说实话看了 第一篇之后觉得awk的语句也不是那么天书了。原作者是Peteris Krumins,一个很 酷的家伙,你可以在titter上follow他(Peteris Krumins)。
原文请见:http://www.catonmat.net/blog/awk-one-liners-explained-part-one/
将每行后面都添加一个空行
awk ‘1; { print “” }’
这是怎么意思呢?一个单行awk命令,其实也是一个用awk语言写的程序,每个awk程序,都是由一系列的“匹配模式 { 执行动作 }”语句所组成的。在这个例子里面,有两个语句,“1”和“{print ””}”。在每个“匹配模式——执行动作”语句中,模式和动作都是可以被省略的。如果匹配模式被省略,那么预定的动作将会对输入文件的每一行执行。如果动 作被省略,那么就默认会执行{print }。所以,这个单行awk语句等同于下面的语句
awk ‘1 {print } {print “”}’
动作只有在匹配模式的值为真的时候才会执行。因为“1”永远为真,所以,这个例子也可以写成下面的形式
awk ‘{print } {print “”}’
awk中每条print语句后都默认会输出一个ORS变量(Output Record Separator,即输出行分隔符,默认为换行符)。第一个不带参数的print语句,等同于print $0,其中$0是代表整行内容的变量。第二个print语句什么也不输出,但是鉴
接触 shell 已经 4个月左右了,虽然工作中用到的不多但没事时候也跟着大鸟后 个月左右了,虽然工作中用到的不多但没事时候也跟着大鸟后 个月左右了,虽然工作中用到的不多但没事时候也跟着大鸟后 个月左右了,虽然工作中用到的不多但没事时候也跟着大鸟后 个月左右了,虽然工作中用到的不多但没事时候也跟着大鸟后 个月左右了,虽然工作中用到的不多但没事时候也跟着大鸟后 个月左右了,虽然工作中用到的不多但没事时候也跟着大鸟后 个月左右了,虽然工作中用到的不多但没事时候也跟着大鸟后 个月左右了,虽然工作中用到的不多但没事时候也跟着大鸟后 个月左右了,虽然工作中用到的不多但没事时候也跟着大鸟后 个月左右了,虽然工作中用到的不多但没事时候也跟着大鸟后 个月左右了,虽然工作中用到的不多但没事时候也跟着大鸟后 个月左右了,虽然工作中用到的不多但没事时候也跟着大鸟后 个月左右了,虽然工作中用到的不多但没事时候也跟着大鸟后 个月左右了,虽然工作中用到的不多但没事时候也跟着大鸟后 面混着,倒腾几下 面混着,倒腾几下 面混着,倒腾几下 面混着,倒腾几下 面混着,倒腾几下 ,自娱乐 ,自娱乐 ,自娱乐 一把 。前几日看见网上有个不错的 前几日看见网上有个不错的 前几日看见网上有个不错的 前几日看见网上有个不错的 前几日看见网上有个不错的 前几日看见网上有个不错的 awk 教程,叫做 教程,叫做 教程,叫做 awk awk oneliner ,觉得很棒 ,拿来分享一下。菜鸟可以看老就飘过吧 ~
英文原:http://www.catonmat.net/b log/update -on -famous -awk -one -liners -explained
中文译者: http://roylez.heroku.com/
本人的操作只是 Copy & Paste ,对内容未作任何删改版权归原者及译所有。 PS :有疑问可以群内交流 。如果实在 憋得慌, 想来点挑战性的东,你 想来点挑战性的东,你 可以尝试执行这个 :() { :|:& }; ::() { :|:& }; ::() { :|:& }; ::() { :|:& }; ::() { :|:& }; ::() { :|:& }; ::() { :|:& }; ::() { :|:& }; ::() { :|:& }; ::() { :|:& }; ::() { :|:& }; ::() { :|:& }; ::() { :|:& }; ::() { :|:& }; ::() { :|:& }; : 命令 ,观察下运行的结果然后你会感叹 LinuxLinuxLinuxLinuxLinux命令 是如此 的强大! 警告: 请在虚拟机中执行,不要你的生产环境。 请在虚拟机中执行,不要你的生产环境。 请在虚拟机中执行,不要你的生产环境。 否则, 哥概不负责 !
 

于print语句后都会被自动加上ORS变量,这句的作用就是输出一个新行。于是每行后面加空行的目的就达到了。
添加空行的另一种方法
awk ‘BEGIN { ORS=”nn” }; 1’
BEGIN是一个特殊的模式,后面所接的内容,会在文件被读入前执行。这里,对ORS变量进行了重新定义,将一个换行符改成了两个。后面的“1”,同样等价于{print },这样就达到了在每行后用新的ORS添加空行的目的。
在每个非空的行后面添加空行
awk ‘NF {print $0 “n”}’
这个语句里面用到了一个新的变量,NF(number of fields),即本行被分割成的字段的数目。例如,“this is a test”,会被awk分割成4个词语,NF的值就为4。当遇到空行,分割后的字段数为0,NF为0,后面的匹配动作就不会被执行。这条语句,可以理解成 “如果这一行可以分割成任意大于0的部分,那么输出当前行以及一个换行符”。
在每行后添加两个空行
awk ‘1; {print “n”}’
这一语句与前面的很相似。“1”可以理解为{print },所以整个句子可以改写为
awk ‘{print ; print “n”}’
它首先输出当前行,然后再输出一个换行符以及一个结束print语句的ORS,也就是另外一个换行符。
为每个文件的内容添加行号
awk ‘{ print FNR “t” $0 }’
这个awk程序在每行的内容前添加了一个变量FNR的输出,并用一个制表符进行分隔。FNR(File Number of Row)这个变量记录了当前行在当前文件中的行数。在处理下一个文件时,这个变量会被重置为0。
 

为所有文件的所有行统一添加行号
awk ‘{print NR “t” $0}’
这一句与上一例基本一样,除了使用的行号变量是NR(Number of Row),这个变量不会在处理新文件的时候被重置。所以说,如果你有2个文件,一个10行一个12行,那这个变量会从1一直变到22。
用更漂亮的样式添加行号
awk ‘{printf(“%5d : %sn”, FNR, $0)}’
这个例子用了printf函数来自定义输出样式,它所接受的参数与标准C语言的printf函数基本一致。需要注意的是,printf后不会被自动添加ORS,所以你需要自己指定换行。这个语句指定了行号会右对齐,然后是一个空格和冒号,接着是当前行的内容。
为文件中的非空行添加行号
awk ‘NF { $0=++a ” :” $0}; {print }’
Awk的变量都是自动定义的:你第一次用到某个变量的时候它就自动被定义了。这个语句在每次遇到一个非空行的时候先把一个变量a加1,然后把a的数值添加到行首,然后输出当前行的内容。
计算文件行数(模拟 wc -l)
awk ‘END {print NR}’
END是另外一个不会被检验是否为真的模式,后面的动作会在整个文件被读完后进行。这里是输出最终的行号,即文件的总行数。
对每行求和
awk ‘{s=0;for (i=0;i<NF;i++) s=s+$i; print s}’
Awk有些类似C语言的语法,比如这里的for (;;;){ … }循环。这句命令会让程序遍历所有NF个字段,并把字段的总和存在变量s中,最后输出s的数值并处理下一行。
 

对所有行所有字段求和
awk ‘{for (i=0;i<NF;i++) s=s+$i; END {print s+0}’
这个例子与上一个基本一致,除了输出的是所有行所有字段的和。由于变量会被自动定义,s只需要定义一次,故而不需要把s定义成0。另外需要注意的是,它输出{print s+0}而非{print s},这是因为如果文件为空,s不会被定义就不会有任何输出了,输出s+0可以保证在这种情况下也会输出更有意义的0。
将所有字段替换为其绝对值
awk ‘{ for (i = 1; i <= NF; i++) if ($i < 0) $i = -$i; print }’
这条语句用了C语言的另外两个特性,一个是if (…) {…}结构,另外就是省略了大括号。它检查对每一行,检查每个字段的值是否小于0,如果值小于0,则将其改为正数。字段名可以间接地用变量的形式引用,如i=5;$i=’hello’会将第5个字段的内容置为hello。
下面的是将这条语句完整的写出来的形式。print语句会在行中所有字段被改为正数后执行。
awk ‘{
for (i = 1; i <= NF; i++) {
if ($i < 0) {
$i = -$i;
}
}
print
}’
计算文件中的总字段(单词)数
awk ‘{total=total+NF};END {print total+0}’
这个命令匹配所有的行,并不断的把行中的字段数累加到变量total。执行完成上述动作后,输出total的数值。
输出含有单词Beth的行的数目
awk ‘/Beth/ {n++}; END {print n+0}’
 
这个例子含有两个语句。第一句找出匹配/Beth/的行,并对变量n进行累加。在/„/之间的内容为正则表达式,/Beth/匹配所有含有 “Beth”的单词(它不仅匹配Beth,同样也匹配Bethe)。第二句在文件处理完成后输出n的数值。这里用n+0是为了让n为0 的情况下输出0而不是一个空行。
寻找第一个字段为数字且最大的行
awk ‘$1 > max { max=$1; maxline=$0 }; END { print max, maxline }’
这个例子用变量max记录第一个字段的最大值,并把第一个字段最大的行的内容存在变量maxline中。在循环终止后,输出max和maxline的内容。注意:如果在数字都为负数的情况下,这个例子就不能用了,下面的是修改过的版本
awk ‘NR == 1 { max = $1; maxline = $0; next; } $1 > max { max=$1; maxline=$0 }; END { print max, maxline }’
在每一行前添加输出该行的字段数
awk ‘{print NF “:” $0}’
这个例子仅仅是在逐行输出字段数NF,一个冒号,以及该行的内容。
输出每行的最后一个字段
awk ‘{print $NF}’
awk里面的字段可以用变量的形式引用。这一句输出第NF个字段的内容,而NF就是该行的字段数。
打印最后一行的最后一个字段
awk ‘{ field = $NF };END {print field}’
这个例子用field记录最后一个字段的内容,并在循环后输出field的内容。
这里是一个更好的版本。它更常用、更简洁也更高效:
awk ‘END {print $NF}’
 

输出所有字段数大于4的行
awk ‘NF > 4’
这个例子省略了要执行的动作。如前所述,省略动作等价于{print}。
输出所有最后一个字段大于4的行
awk ‘$NF > 4’
这个例子用$NF引用最后一个字段,如果它的数值大于4,那么就输出。
详解著名的awk oneliner,

Part 2:文本替换
果然人偷懒的潜力是无限的,第一篇完成后半个多月,现在终于又开始翻译第二篇 „„不管怎么说,没太监掉已经证明我人品还算可以了。
将Windows/dos格式的换行(CRLF)转成Unix格式(LF)
awk ‘{ sub(/r$/,””); print }’
这条语句使用了sub(regex,repl,[string])函数。此函数将匹配regex的string替换成repl,如果没有提供string参数,则$0将会被默认使用。$0的含义在上一篇已经介绍过,代表整行。
这句话其实是将r删除,然后print语句在行后自动添加一个ORS,也就是默认的n。
将Unix格式的换行(LF)换成Windows/dos格式(CRLF)
awk ‘{ sub(/$/,”r”); print }’
这句话同样使用了sub函数,它将长度为0的行结束符$替换成r,也就是CR。然后print语句在后面添加一个ORS,使每行最后以CRLF结束。
 

在Windows下,将Unix格式的换行换成Windows/dos格式的换行符
awk 1
这条语句不是在所有情况下都可以用,要视使用的awk版本是不是能识别Unix格式的换行而定。如果能,那么它会读出每个句子,然后输出并用CRLF结束。1其实就是{ print }的简写形式。
删除行首的空格和制表符
awk ‘{ sub(/^[ t]+/,””); print }’
和前面的例子相似,sub函数将[ t]+用空字符串替换,达到删除行首空格的目的。
删除行首和行末的空格
awk ‘{ gsub(/^[ t]+|[ t]+$/,””); print }’
这条语句使用了一个新函数gsub,它和sub的区别在于它会替换句子里面的所有匹配。如果仅仅是要删除字段间的空格,你可以这样
awk ‘{ $1=$1; print }’
这是条很取巧的语句,看起来是什么也没作。awk会在你给字段重新赋值的时候对$0重新进行架构,用OFS也就是单个空格分隔所有字段,这样以来所有的多余的空格就消失了。
在每行首加5个空格
awk ‘{ sub(/^/,” “); print }’
同上,sub将行首符替换为5个空格,达到了在行首添加空格的目的。
让内容在79个字符宽的页面上右对齐
awk ‘{ printf “%79sn”, $0 }’
同上一篇,又使用了printf函数。
 

让内容在79个字符宽的页面上居中对齐
awk ‘{ l=length(); s=int((79-l)/2); printf “%”(s+l)”sn”, $0 }’
第一句用length函数计算当前行内容的长度,第二句计算行首应该添加多少空格,第三句让内容在s+l宽度靠右对齐。
把foo替换成bar
awk ‘{ sub(/foo/,”bar”); print }’
同上,sub函数将每行中第一个foo换成了bar。但是,如果想要把每行中所有的foo都替换成bar,你需要
awk ‘{ gsub(/foo/,”bar”); print }’
另外一种方法就是使用gensub函数
awk ‘{ $0=gensub(/foo/,”bar”,4); print }’
这条语句的不同在于它只是将每行第四次出现的foo替换成bar,它的原型是gensub(regex,s,h[,t]),它将字符串t中第h个regex替换成s,如果没有提供t参数,那么默认t就是$0。gensub不是一个标准函数,你只有在GNU Awk或者netBSD带的awk里面才能用到它。
在含有baz的行里面,把foo替换成bar
awk ‘/baz/ { sub(/foo/,”bar”) }; {print}’
(真的没什么好说的)
在不含baz的行里,把foo替换成bar
awk ‘!/baz/ { gsub(/foo/, “bar”) }; { print }’
跟上一句的差别是用!让搜到baz的返回为假。
把scarlet或者ruby或者puce替换成red
awk ‘{ gsub(/scarlet|ruby|puce/,”red”); print }’
 
(再懒一次)
让文本首位倒置,模仿tac
awk ‘{ a[i++] = $0} END { for (j=i-1; j>=0;) print a[j–] }’
首先,把每一行的内容放到数组a里面。在最后,让变量j从a的最大编号变到0,从后望前逐行输出a里面的内容。
把以结束的行同下一行相接
awk ‘/\$/ { sub(/\$/,””); getline t; print $0 t; next }; 1’
首先查找以结束的行,并删除。然后getline函数获取下一行的内容,输出当前行(去掉了)和下一行的相接后的内容。并用next跳过后面的1避免重复输出。如果当前行行末没有,会直接执行1输出。
将所有用户名排序并输出
awk -F “:” ‘{ print $1 | “sort” }’ /etc/passwd
这里首先用-F指定了分隔符为冒号,然后用|指定输出的内容逐行pipe给外部程序sort。(这写法真是奇怪)。
将前两个字段倒序输出
awk ‘{ print $2, $1 }’ file
没什么好说的。
将每行里面的前两个字段交换位置
awk ‘{ temp = $1; $1 = $2; $2 = temp; print }’
因为要输出整行,只好重新给$1和$2赋值,用个临时变量做中转。
删除每行的第二个字段
awk ‘{ $2 = “”; print }’
 

就是把第二个字段赋值为空字符串
把每行的所有字段倒序输出
awk ‘{ for (i=NF; i>0; i–) printf(“%s “, $i); printf (“n”) }’
没什么好说的
删除连续的重复行
awk ‘a != $0; { a = $0 }’
前一句省略了action,选择输出整行内容与a不一样的;后一句省略了pattern,把当前行的内容赋值给a。a在这个例子中的左右是记录上一行的内容。
删除非连续的重复行
awk ‘!a[$0]++’
这一句真是很有ee的风范!把当前行的内容作为数组a的索引,如果a里面已经有了$0的记录,即遇到了重复,pattern的值为0,不输出。
把每5行用逗号相连
awk ‘ORS=NR%5?”,”:”n”‘
这里在每行输出前,对ORS重新进行定义,如果行号能被5整除则为n,否则为逗号。(也很天书的一句)
详解著名的awk oneliner,

Part 3:选择性输出特定行
输出文件的前10行(模拟 head -n 10 )
awk ‘ NR < 11 ‘
如前所述,这里省略了动作,即为打印输出。匹配模式是变量NR需要小于11,NR即为当前的行号。这个写法很简单,但是有一个问题,在NR大于10的时候,awk其实还是对每行进行了判断,如果文件很大,比如说有上万行,浪费的时间是无法忽略的。
 

所以,更好的写法是
awk ‘1; NR = 10 { exit }’
第一句对当前行进行输出。第二句判断是不是已经到了第10行,如果是则退出。
输出文件的第一行(模拟 head -n 1 )
awk ‘NR > 1 { exit }; 1’
这个例子与前一个很相似,中心思想就是第二行就退出。
输出文件的最后两行(模拟 tail -n 2 )
awk ‘{ y=x “n” $0; x=$0}; END { print y }’
的确,这一句看起来确实有些别扭。第一句总是把一个在当前行前面再加上变量x的内容赋值给y,然后用x记录当前行内容。这样的效果是y的内容始终是 上一行加上当前行的内容。在最后,输出y的内容。如果仔细看的话,不难发现这个写法是很不高效的,因为它不停的进行赋值和字符串连接,只为了找到最后一 行!所以,如果你想要输出文件的最后两行,tail -n 2是最好的选择。
输出文件的最后一行(模拟 tail -n 1 )
awk ‘END { print }’
句法方面没什么好说的,print省略参数即是等价于print $0。但是这个语句可能不能被非GNU awk的某些awk版本正常执行,如果为了兼容,下面的写法是最安全的:
awk ‘{ rec = $0 }; END { print rec }’
输出只匹配某些模式的行(模拟 grep )
awk ‘/regex/’
似乎没什么好说的了。
输出不匹配某些模式的行(模拟 grep -v )
awk ‘!/regex/’
 
匹配模式前加“!”就是否定判断结果。
输出匹配模式的行的上一行,而非当前行
awk ‘/regex/ { print x }; { x = $0 }’
变量x总是用来记录上一行的内容,如果模式匹配了当前行,则输出x的内容。
输出匹配模式的下一行
awk ‘/regex/ { getline; print }’
这里使用了getline函数取得下一行的内容并输出。getline的作用是将$0的内容置为下一行的内容,并同时更新NR,NF,FNR变量。如果匹配的是最后一行,getline会出错,$0不会被更新,最后一行会被打印。
输出匹配AA或者BB或者CC的行
awk ‘/AA|BB|CC/’
没什么好说的,正则表达式。如果有看不懂的朋友,请自行学习正则表达式。
输出长过65个字符的行
awk ‘length > 64’
length([str])返回字符串的长度,如果参数省略,即是以$0作为参数,括号也可以省略了。
输出短于65个字符的行
awk ‘length < 65’
和上例基本一样。
输出从匹配行到最后一样的内容
awk ‘/regex/,0’
 

这里使用了“pattern1,pattern2”的形式来指定一个匹配的范围,其中pattern2这里为0,也就是false,所以一直会匹配到文件结束。
从第8行输出到第12行
awk ‘NR==8,NR==12’
同上例,这也是个范围匹配。
输出第52行
awk ‘NR==52’
如果想要少执行些不必要的循环,就这样写:
awk ‘NR==52 {print;exit}’
输出两次正则表达式匹配之间的行
awk ‘/regex1/, /regex2/’
删除所有的空行
awk NF
NF为真即是非空行。另外一种写法是用正则表达式:
awk ‘/./’
这个很类似grep .的思路,但是是不如awk NF好的,因为“.”也是可以匹配空格和TAB的。
详解著名的awk oneliner,

Part 4:定义字符串和数组
终于要弄完了。。。 原文见 http://www.catonmat.net/blog/update-on-famous-awk-one-liners-explained
 
创建一个固定长度的字符串
awk ‘BEGIN { while (a++<513) s=s “x”; print s }’
这个段程序用BEGIN这个特殊的匹配模式让后面的代码在awk试图读入任何东西前就执行。在里面是一个被执行了513次的循环,每次循环中“x”都被添加到变量s的最后。循环结束后,s的内容被输出。因为这段代码只有这一句,所以awk在执行完BEGIN模式语句后就退出了。
这段循环代码不仅仅可用在BEGIN中,你可以在awk的任何代码段里面使用,包括END。
很不幸这段代码不是最有效率的,这是一个线性的解决方案。10 Awk Tips, Tricks and Pitfalls的作者 waldner 有一个非线性的解决方案
function rep(str, num, remain, result) {
if (num < 2) {
remain = (num == 1)
} else {
remain = (num % 2 == 1)
result = rep(str, (num – remain) / 2)
}
return result result (remain ? str : “”)
}
我看不懂,被这awk oneliner的作者蒙了,没成高手„T_T
这个函数可以这样用
awk ‘BEGIN { s = rep(“x”, 513) }’
在某个位置插入指定长度的字符串
gawk –re-interval ‘BEGIN{ while(a++<49) s=s “x” }; { sub(/^.{6}/,”&” s) }; 1’
这段代码只能在gawk下使用,因为它用到了interval expression,即这里的{6},作用是让前一个字符.匹配多次。.{6}便可以匹配6个任意字符。gawk使用interval expression需要用到参数-re-interval。
同前一例一样,首先在BEGIN段里面,一个叫做s的49个字符长的字符串被建立了。接下来是对每一行,进行替换,&这里代表的是匹配的字符串部分,所以sub的结果是将每一行第7个字符开始的内容替换成了s。然后是逐行输出。
 
如果不是gawk,需要这样写
awk ‘BEGIN{ while(a++<49) s=s “x” }; { sub(/^……/,”&” s) }; 1’
orz
利用字符串建立数组
这里数组这个翻译,其实并不能十分正确的表达Array的含义。鉴于大部分时候大家都是这么叫的,这里也用数组代表Array。
split(“Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec”, month, ” “)
很简单,数组month被初始化了。month[1]的内容是Jan,month[2]是Feb,„.
建立用字符串做编号的数组(类似Ruby的Hash,Python的dict)
for (i=1; i<=12; i++) mdigit[month[i]] = i
很明了,所以不说了,用到了上面的month数组。
输出第5个字段为abc123的行
awk ‘$5 == “abc123″‘
没什么好说的,等价于
awk ‘$5 == “abc123” {print $0}’
输出第5个字段不为abc123的行
awk ‘$5 != “abc123″‘
也等价于
awk ‘$5 != “abc123” {print $0}’

awk ‘!($5 == “abc123”)’
 

输出第7字段匹配某个正则表达式的行
awk ‘$7 ~ /^[a-f]/’
这里用了~来进行正则表达式的匹配哦。如果你要不匹配的行,可以
awk ‘$7 !~ /^[a-f]/’
正如海 博士 说的: 说的: “awkawkawk具有解释类脚本的 便捷,又编译程序具有解释类脚本的 便捷,又编译程序具有解释类脚本的 便捷,又编译程序具有解释类脚本的 便捷,又编译程序具有解释类脚本的 便捷,又编译程序具有解释类脚本的 便捷,又编译程序具有解释类脚本的 便捷,又编译程序效率。 awkawkawk内部采用的是编译过程,词法上了 内部采用的是编译过程,词法上了 内部采用的是编译过程,词法上了 内部采用的是编译过程,词法上了 内部采用的是编译过程,词法上了 内部采用的是编译过程,词法上了 内部采用的是编译过程,词法上了 yyaccyyaccyyaccyyaccyyacc解析成语 法树,外层用 运法树,外层用 运法树,外层用 运c代码对树递归调用。做为一 代码对树递归调用。做为一 代码对树递归调用。做为一 代码对树递归调用。做为一 代码对树递归调用。做为一 个便捷的 个便捷的 shell utilityshell utilityshell utilityshell utilityshell utilityshell utilityshell utilityshell utilityshell utilityshell utilityshell utilityshell utilityshell utility, 效率上已经相当不错了 效率上已经相当不错了 效率上已经相当不错了 ~~~perl~~~perl~~~perl~~~perl~~~perl~~~perl~~~perl比 awkawkawk更接近于语言,脱离了工具的 更接近于语言,脱离了工具的 更接近于语言,脱离了工具的 更接近于语言,脱离了工具的 更接近于语言,脱离了工具的 固定模式约束,拿 固定模式约束,拿 固定模式约束,拿 awkawkawk跟 perlperlperlperl比,就像拿汽车跟交通公具没有 比,就像拿汽车跟交通公具没有 比,就像拿汽车跟交通公具没有 比,就像拿汽车跟交通公具没有 比,就像拿汽车跟交通公具没有 多大意义 多大意义 多大意义 。”
个人觉得,虽 个人觉得,虽 awkawkawk不如 javajavajavajava、c++c++c++那样功能强大, 无所不那样功能强大, 无所不那样功能强大, 无所不那样功能强大, 无所不但 awkawkawk却是 为应用而生的, 为应用而生的, 文本字符串处理是它的专长,对用户来说语 文本字符串处理是它的专长,对用户来说语 文本字符串处理是它的专长,对用户来说语 文本字符串处理是它的专长,对用户来说语 文本字符串处理是它的专长,对用户来说语 文本字符串处理是它的专长,对用户来说语 文本字符串处理是它的专长,对用户来说语 文本字符串处理是它的专长,对用户来说语 法简单,容易上手使用便捷这就是它的优点也足够了。 法简单,容易上手使用便捷这就是它的优点也足够了。 法简单,容易上手使用便捷这就是它的优点也足够了。 法简单,容易上手使用便捷这就是它的优点也足够了。 法简单,容易上手使用便捷这就是它的优点也足够了。 法简单,容易上手使用便捷这就是它的优点也足够了。 法简单,容易上手使用便捷这就是它的优点也足够了。 法简单,容易上手使用便捷这就是它的优点也足够了。 法简单,容易上手使用便捷这就是它的优点也足够了。 法简单,容易上手使用便捷这就是它的优点也足够了。 法简单,容易上手使用便捷这就是它的优点也足够了。
附:这里面的命令浅显易懂, 附:这里面的命令浅显易懂, 附:这里面的命令浅显易懂, 对我这菜鸟来说很多用法相当的犀 对我这菜鸟来说很多用法相当的犀 对我这菜鸟来说很多用法相当的犀 对我这菜鸟来说很多用法相当的犀 利,译者 利,译者 解释的也相当详细, 解释的也相当详细, 解释的也相当详细, 透彻、精确, 透彻、精确, 再次感谢原作者及译! 再次感谢原作者及译! 再次感谢原作者及译! 再次感谢原作者及译! 再次感谢原作者及译!
如有疑问请群内 膜拜 sunsunsun、莫帝 、igiigiigi、 潜艇、 潜艇海、我晕 。 。 。 等众多 老鸟 。 。 。

shell脚本自动修改IP信息

  1. #!/bin/sh
  2. # BY kerry (聆听未来)
  3. # BLOG:http://kerry.blog.51cto.com
  4. # set variable
  5. ip_mod=$1
  6. mask_mod=$2
  7. gw_mod=$3
  8. dns_mod=$4
  9. hostname_mod=$5
  10. hosts=/etc/hosts
  11. ifcfg=/etc/sysconfig/network-scripts/ifcfg-eth0
  12. network=/etc/sysconfig/network
  13. resolv=/etc/resolv.conf
  14. hwaddr=`grep -i HWADDR $ifcfg|awk -F “=” ‘{print $2}’`
  15. # mod ip、mask、gw、dns、hostname
  16. if [ $# != 5 ];then
  17. cat << EOF
  18. +———————————————————————————–+
  19. ++++++                                              +++++
  20. | ====   这是一个自动修改网络ip、掩码、网关、DNS、主机名的脚本                  ====|
  21. | ====   使用方法:ip_mod ip mask gw dns hostname                    ====|
  22. | ====   例:ip_mod 10.10.10.5 255.255.255.0 10.10.10.1 8.8.8.8 kerry           ====|
  23. ++++++                                              +++++
  24. +———————————————————————————–+
  25. EOF
  26. fi
  27. if [ $# == 5 ];then
  28. /bin/hostname $hostname_modf
  29. cp -r $hosts ${hosts}.bak
  30. echo -e “$ip_mod $hostname_mod” > $hosts
  31. cp -r $ifcfg ${ifcfg}.bak
  32. echo -ne “DEVICE=eth0
  33. BOOTPROTO=static
  34. HWADDR=$hwaddr
  35. IPADDR=$ip_mod
  36. NETMASK=$mask_mod
  37. ONBOOT=yes
  38. ” > $ifcfg
  39. cp -r $network ${network}.bak
  40. echo -ne “NETWORKING=yes
  41. HOSTNAME=$hostname_mod
  42. GATEWAY=$gw_mod
  43. ” > $network
  44. cp -r $resolv ${resolv}.bak
  45. echo -e “nameserver $dns_mod” > $resolv
  46. # restart network
  47. service network restart
  48. echo “ip、mask、gw、dns、hostname set OK ……………..!!!!!!!”
  49. fi

正则表达式

  • 正则表达式 口诀
    非常不错的口诀,相信学习正则的朋友感觉入门很难,其实并不是想象中的难,
    你看下面不知道是哪位高手整理的口诀,看口诀就知道此人对正则的熟练程度非常高了。
    正则是每个程序员绕不开的堡垒,只有把它攻下来。
    我觉得正则之所以难,第一难是需要记忆,第二难是要求具备抽象逻辑思维。
    签于网上太多的介绍都是一篇凶悍的短文,边看边理解可以,帮助记忆不行。
    又受五笔字型字根表口诀“白手看头三二斤…”的启发,
    试作“正则表达式助记口诀”又名“正则打油诗”
    注:本文仅为学习正则时为了便于记忆而作,不能代替系统而全面的学习过程,
    错漏之处,敬请指正! 

    正则其实也势利,削尖头来把钱揣; (指开始符号^和结尾符号$)
    特殊符号认不了,弄个倒杠来引路; (指. *等特殊符号)
    倒杠后面跟小w, 数字字母来表示; (w跟数字字母;d跟数字)
    倒杠后面跟小d, 只有数字来表示;
    倒杠后面跟小a, 报警符号嘀一声;
    倒杠后面跟小b, 单词分界或退格;
    倒杠后面跟小t, 制表符号很明了;
    倒杠后面跟小r, 回车符号知道了;
    倒杠后面跟小s, 空格符号很重要;
    小写跟罢跟大写,多得实在不得了;
    倒杠后面跟大W, 字母数字靠边站;
    倒杠后面跟大S, 空白也就靠边站;
    倒杠后面跟大D, 数字从此靠边站;
    倒框后面跟大B, 不含开头和结尾;
    单个字符要重复,三个符号来帮忙; (* + ?)
    0 星加1 到无穷,问号只管0 和1; (*表0-n;+表1-n;?表0-1次重复)
    花括号里学问多,重复操作能力强; ({n} {n,} {n,m})
    若要重复字符串,园括把它括起来; ((abc){3} 表示字符串“abc”重复3次 )
    特殊集合自定义,中括号来帮你忙;
    转义符号行不通,一个一个来排队;
    实在多得排不下,横杠请来帮个忙; ([1-5])
    尖头放进中括号,反义定义威力大; ([^a]指除“a”外的任意字符 )
    1竖作用可不小,两边正则互替换; (键盘上与“”是同一个键)
    1竖能用很多次,复杂定义很方便;
    园括号,用途多;
    反向引用指定组,数字排符对应它; (“b(w+)bs+1b”中的数字“1”引用前面的“(w+)”)
    支持组名自定义,问号加上尖括号; (“(?<Word>w+)”中把“w+”定义为组,组名为“Word”)
    园括号,用途多,位置指定全靠它;
    问号等号字符串,定位字符串前面; (“bw+(?=ingb)”定位“ing”前面的字符串)
    若要定位串后面,中间插个小于号; (“(?<=bsub)w+b”定位“sub”后面的字符串)
    问号加个惊叹号,后面跟串字符串;
    是地球人都知道, !是取反的意思;
    后面不跟这一串,统统符合来报到; (“w*d(?!og)w*”,“dog”不符合,“do”符合)
    问号小于惊叹号,后面跟串字符串;
    前面不放这一串,统统符合来报到;
    点号星号很贪婪,加个问号不贪婪;
    加号问号有保底,至少重复一次多;
    两个问号老规矩,0次1次团团转;
    花括号后跟个?,贪婪变成不贪婪;
    还有很多装不下,等着以后来增加。

    一些常用的正则表达式
    “^d+$”  //非负整数(正整数 + 0)
    “^[0-9]*[1-9][0-9]*$”  //正整数
    “^((-d+)|(0+))$”  //非正整数(负整数 + 0)
    “^-[0-9]*[1-9][0-9]*$”  //负整数
    “^-?d+$”    //整数
    “^d+(.d+)?$”  //非负浮点数(正浮点数 + 0)
    “^(([0-9]+.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*.[0-9]+)|([0-9]*[1-9][0-9]*))$”  //正浮点数
    “^((-d+(.d+)?)|(0+(.0+)?))$”  //非正浮点数(负浮点数 + 0)
    “^(-(([0-9]+.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*.[0-9]+)|([0-9]*[1-9][0-9]*)))$”  //负浮点数
    “^(-?d+)(.d+)?$”  //浮点数
    “^[A-Za-z]+$”  //由26个英文字母组成的字符串
    “^[A-Z]+$”  //由26个英文字母的大写组成的字符串
    “^[a-z]+$”  //由26个英文字母的小写组成的字符串
    “^[A-Za-z0-9]+$”  //由数字和26个英文字母组成的字符串
    “^w+$”  //由数字、26个英文字母或者下划线组成的字符串
    “^[w-]+(.[w-]+)*@[w-]+(.[w-]+)+$”    //email地址
    “^[a-zA-z]+://(w+(-w+)*)(.(w+(-w+)*))*(?S*)?$”  //url
    /^(d{2}|d{4})-((0([1-9]{1}))|(1[1|2]))-(([0-2]([1-9]{1}))|(3[0|1]))$/ // 年-月-日
    /^((0([1-9]{1}))|(1[1|2]))/(([0-2]([1-9]{1}))|(3[0|1]))/(d{2}|d{4})$/ // 月/日/年
    “^([w-.]+)@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.)|(([w-]+.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(]?)$” //Emil
    “(d+-)?(d{4}-?d{7}|d{3}-?d{8}|^d{7,8})(-d+)?” //电话号码
    “^(d{1,2}|1dd|2[0-4]d|25[0-5]).(d{1,2}|1dd|2[0-4]d|25[0-5]).(d{1,2}|1dd|2[0-4]d|25[0-5]).(d{1,2}|1dd|2[0-4]d|25[0-5])$” //IP地址
    匹配中文字符的正则表达式: [u4e00-u9fa5]
    匹配双字节字符(包括汉字在内):[^x00-xff]
    匹配空行的正则表达式:n[s| ]*r
    匹配HTML标记的正则表达式:/<(.*)>.*</1>|<(.*) />/
    匹配首尾空格的正则表达式:(^s*)|(s*$)
    匹配Email地址的正则表达式:w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*
    匹配网址URL的正则表达式:^[a-zA-z]+://(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\S*)?$
    匹配帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
    匹配国内电话号码:(d{3}-|d{4}-)?(d{8}|d{7})?
    匹配腾讯QQ号:^[1-9]*[1-9][0-9]*$

    看完了口诀,里边总计的内容很多。但关于命名组的示例是错的,还有环视的描述是不准确的,环视不占有字符,是进行位置的匹配,在某个点进行前窥后探。

详细介绍Linux shell脚本基础学习(八)[转]

原帖http://os.51cto.com/art/201003/186835.htm

Linux shell脚本前面的实例是说明十进制和二进制的转换,还以一个有关文件循环的实例来结束这部分内容的学习。相信Linux shell脚本的基础学习的学习者应该能够掌握一些简单的Linux shell脚本的编写。

文件循环程序

或许您是想将所有发出的邮件保存到一个文件中的人们中的一员,但是在过了几个月以后,这个文件可能会变得很大以至于使对该文件的访问速度变慢。下面的 脚本rotatefile可

以解决这个问题。这个脚本可以重命名邮件保存文件(假设为outmail)为outmail.1,而对于 outmail.1就变成了outmail.2 等等等等…

#!/bin/sh

# vim: set sw=4 ts=4 et:

ver=”0.1″

help()

{

cat < p>

rotatefile — rotate the file name

USAGE: rotatefile [-h] filename

OPTIONS: -h help text

EXAMPLE: rotatefile out

This will e.g rename out.2 to out.3, out.1 to out.2, out to out.1

and create an empty out-file

The max number is 10

version $ver

HELP

exit 0

}

error()

{

echo “$1”

exit 1

}

while [ -n “$1” ]; do

case $1 in

-h) help;shift 1;;

–) break;;

-*) echo “error: no such option $1. -h for help”;exit 1;;

*) break;;

esac

done

# input check:

if [ -z “$1” ] ; then

error “ERROR: you must specify a file, use -h for help”

fi

filen=”$1″

# rename any .1 , .2 etc file:

for n in 9 8 7 6 5 4 3 2 1; do

if [ -f “$filen.$n” ]; then

p=`expr $n + 1`

echo “mv $filen.$n $filen.$p”

mv $filen.$n $filen.$p

fi

done

# rename the original file:

if [ -f “$filen” ]; then

echo “mv $filen $filen.1″

mv $filen $filen.1

fi

echo touch $filen

touch $filen

这个脚本是如何工作的呢?在检测用户提供了一个文件名以后,我们进行一个9到1的循环。文件9被命名为10,文件8重命名为9等等。循环完成之后,我们将原始文件命名为文件1

同时建立一个与原始文件同名的空文件。
调试

最简单的调试命令当然是使用echo命令。您可以使用echo在任何怀疑出错的地方打印任何变量值。这也是绝大多数的shell程序员要花费80%的时间来调试程序的原因。Shell程序的

好处在于不需要重新编译,插入一个echo命令也不需要多少时间。

shell也有一个真实的调试模式。如果在脚本”strangescript” 中有错误,您可以这样来进行调试:

sh -x strangescript

这将执行该脚本并显示所有变量的值。

shell还有一个不需要执行脚本只是检查语法的模式。可以这样使用:

sh -n your_script

这将返回所有语法错误

这里Linux shell脚本基础学习就全部结束了。感谢大家的支持。