作者归档:老沙

通过 网络安装 linux

必备服务:
1.DHCP服务
2.tftp服务
3.NFS服务或FTP或HTTP均可
(要求待安装电脑必需支持PXE启动)

配置步骤:
1.DHCP服务器的配置
[root@disk iso]# rpm -qa dhcp* #确定dhcp是否安装
dhcp-3.0pl1-23

[root@disk iso]# vi /etc/dhcpd.conf #我的dhcp配置(可通过rpm -ql dhcp找到范本)
#ddns-update-style interim;
ddns-update-style none; #不更新DDNS
ignore client-updates;
subnet 192.168.1.0 netmask 255.255.255.0 {

# — default gateway
option routers 192.168.1.1;
option subnet-mask 255.255.255.0;

# option nis-domain "domain.org";
# option domain-name "domain.org";
option domain-name-servers 202.106.46.151,202.106.196.115,202.106.0.20;

option time-offset -18000; # Eastern Standard Time
# option ntp-servers 192.168.1.1;
# option netbios-name-servers 192.168.1.1;
# — Selects point-to-point node (default is hybrid). Don't change this unless
# — you understand Netbios very well
# option netbios-node-type 2;

range dynamic-bootp 192.168.1.240 192.168.1.254;
default-lease-time 21600;
max-lease-time 43200;

# we want the nameserver to appear at a fixed address
group pxe {
filename "pxelinux.0";
host ns {
# next-server marvin.redhat.com;
next-server 192.168.1.51;
hardware ethernet 00:0c:29:96:93:05; #待安装电脑的MAC与IP的绑定
fixed-address 192.168.1.240;
}
}}

[root@disk iso]# vi /usr/share/doc/dhcp-3.0pl1/dhcpd.conf.sample
ddns-update-style interim;
ignore client-updates;
subnet 192.168.0.0 netmask 255.255.255.0 {
# — default gateway
option routers 192.168.0.1;
option subnet-mask 255.255.255.0;

option nis-domain "domain.org";
option domain-name "domain.org";
option domain-name-servers 192.168.1.1;

option time-offset -18000; # Eastern Standard Time
# option ntp-servers 192.168.1.1;
# option netbios-name-servers 192.168.1.1;
# — Selects point-to-point node (default is hybrid). Don't change this unless
# — you understand Netbios very well
# option netbios-node-type 2;

range dynamic-bootp 192.168.0.128 192.168.0.255;
default-lease-time 21600;
max-lease-time 43200;

# we want the nameserver to appear at a fixed address
host ns {
next-server marvin.redhat.com;
hardware ethernet 12:34:56:78:AB:CD;
fixed-address 207.175.42.254;
}
}

#如果有多个网卡
[root@disk iso]# cat /etc/sysconfig/dhcpd
# Command line options here
DHCPDARGS=“eth0”

#启动dhcp
[root@disk iso]# /etc/init.d/dhcpd start

#确定dhcp是否开机自动运行
[root@disk iso]# chkconfig –list |grep dhcp
dhcpd 0:关闭 1:关闭 2:关闭 3:启用 4:关闭 5:启用 6:关闭

2.tftp服务配置
[root@disk iso]# rpm -qa |grep tftp
tftp-0.32-4
tftp-server-0.32-4

安装
rpm -ivh tftp-server-0.32-4
rpm -ivh tftp-0.32-4

[root@disk iso]# cat /etc/xinetd.d/tftp
service tftp
{
disable = no
socket_type = dgram
protocol = udp
wait = yes
user = root
server = /usr/sbin/in.tftpd
server_args = -s /tftpboot -c
}
修改项server_args= -s <path> -c,其中<path>处可以改为你的tftp-server的根目录,参数-s指定chroot,-c指定了可以创建文件

3.NFS服务器配置
[root@disk /]# cat /etc/exports
/home/iso 192.168.1.0/24(rw,no_root_squash)
参数包括
rw:可读写
ro:只读
sync:同步写入
async:先暂存于内存中
no_root_squash:如果是root,则以root的权限访问
root_squash:如果是root,则压缩成匿名用户
all_squash:将所有登陆用户压缩成匿名用户
anonuid:将匿名者变为指定的uid
anongid:匿名者指定gid

#启动RPC与NFS(最好先关闭防火墙做测试)
/etc/init.d/portmap start
/etc/init.d/nfs start
确认是否正常
[root@disk /]# /etc/init.d/portmap status
portmap (pid 2024) 正在运行…
[root@disk /]# /etc/init.d/nfs status
rpc.mountd (pid 2425) 正在运行…
nfsd (pid 2417 2416 2415 2414 2413 2412 2411 2410) 正在运行…
rpc.rquotad (pid 2405) 正在运行…
#联机观察
[root@disk /]# showmount -a localhost
All mount points on localhost:
redhat.kumouse.com:/home/iso
[root@disk /]# showmount -e localhost
Export list for localhost:
/home/iso (everyone)
参数
-a 显示联机共享状态
-e 显示某主机的/etc/exports所共享的目录

设置NFS服务器的防火墙
[root@disk /]# cat /etc/sysconfig/nfs
MOUNTD_PORT="815"
#STATD_PORT=""
LOCKD_TCPPORT="2049"
LOCKD_UDPPORT="2049"
在/etc/sysconfig/iptables加入
-A RH-Firewall-1-INPUT -p tcp -s 192.168.1.0/24 -m multiport –dport 111,815,2049 -j ACCEPT
-A RH-Firewall-1-INPUT -p udp -s 192.168.1.0/24 -m multiport –dport 111,815,2049 -j ACCEPT
[root@disk /]#/etc/init.d/iptables restart

在别外一台linux主机上加载试试
[root@redhat mydisk]#mkdir /mydisk
[root@redhat mydisk]# mount -t nfs 192.168.1.200:/home/iso /mydisk
如果不输出信息,说明成功了,可以进去看看,看看是不是和/home/iso中的内容一样

关于NFS更详细的说明见:http://www.kumouse.com/article.asp?id=113

经过以上步骤服务器配置基本就完成了
4.将引导程序加入到TFTP的工作目录中(/etc/xinetd.d/tftp中写的server_args = -s /tftpboot -c)
#将光盘中/isolinux目录下的initrd.img与vmlinuz复制到/tftpboot中
[root@disk]#mkdir /mnt/iso
[root@disk]#mount -o loop,ro RHEL5-U2-i386-AS-disc1.iso /mnt/iso
[root@disk]#cp /mnt/iso/isolinux/initrd.img /tftpboot
[root@disk]#cp /mnt/iso/isolinux/vmlinuz /tftpboot
[root@disk]#mv /tftpboot/initrd.img /tftpboot/initrd-rhel5u2-i386.img
[root@disk]#mv /tftpboot/vmlinuz /tftpboot/vmlinuz-rhel5u2-i386
#将启动镜像文件pxelinux.0复制到/tftpboot中
[root@disk]#cp /usr/lib/syslinux/pxelinux.0 /tftpboot/
#编辑pxelinux.0的配置文件,所有的配置文件都放在启动服务器的/tftpboot/pxelinux.cfg/目录下
[root@disk /]# cat /tftpboot/pxelinux.cfg/default
default rhel5u2-i386
prompt 1
display pxelinux.cfg/list

label rhel5u2-i386
kernel vmlinuz-rhel5u2-i386
append initrd=initrd-rhel5u2-i386.img
label rhel5u2-i386-text
kernel vmlinuz-rhel5u2-i386
append initrd=initrd-rhel5u2-i386.img text

#我们将所有备选Red Hat Linux版本列在文件pxelinux.cfg/list中,它的内容会被pxelinux.0显示出来。

[root@disk /]# cat /tftpboot/pxelinux.cfg/list
Choose one of the following Linux distributions for your installation:
Name Distribution Arch. Installation media
————————————————————————-
rhel5u2-i386 RHEL 5 AS U2 i386 192.1

68.1.51:/home/iso/rhel5u2
rhel5u2-i386-text RHEL 5 AS U2 i386 192.168.1.51:/home/iso/rhel5u2

然后复制镜像文件到/home/iso中,就是nfs共享出来的目录,然后把待安装电脑改成网卡启动就可以安装了

选读:无人值守的安装
[root@bootserver ks]# more ks.cfg
# Kickstart file automatically generated by anaconda.
text 文本形式安装
install
nfs –server=192.168.1.51 –dir=/home/iso/rhel5u2 nfs方法安装
lang en_US.UTF-8
langsupport –default=en_US.UTF-8 en_US.UTF-8
keyboard us
#xconfig –card "S3 Savage/IX" –videoram 15168 –hsync 31.5-37.9 –vsync 50-70 –resolution 800×600 –depth 16 –startxonboot —

de
faultdesktop kde
network –device eth0 –bootproto dhcp
rootpw –iscrypted $1$e68iHGpw$/Qe4meNVXULikjCwDH26F1
firewall –disabled
selinux –disabled
authconfig –enableshadow –enablemd5
timezone Asia/Shanghai
bootloader –location=mbr
# The following is the partition information you requested
# Note that any partitions you deleted are not expressed
# here so unless you clear all partitions first, this is
# not guaranteed to work
#clearpart –all –initlabel
#part / –fstype ext2 –size=5000 分区格式可以根据自己的定义。 注释的话手工分区。分区后以下自动安装
#part swap –size=512
#part /data –fstype ext3 –size=1 –grow
%packages
@ admin-tools
@ editors
@ emacs
@ system-tools
@ legacy-network-server
@ dialup
@ ftp-server
@ network-server
@ compat-arch-support
@ legacy-software-development
@ server-cfg
@ development-tools
kernel-devel
e2fsprogs
kernel
pcmcia-cs
grub
%post

所有以"#"号开头的都是注释。

文件中的nfs –server=192.168.1.51 –dir=/home/iso/rhel5u2选项告诉安装程序:到服务器192.168.138.1的NFS共享目录/home/iso/rhel5u2下寻

找安装介质。Red Hat Linux安装程序足够聪明,可以识别该目录下应该被读取的ISO光盘镜像文件名,所有这里你不需要指定ISO文件名。

部署kickstart配置文件

首先我们需要把kickstart配置文件放在安装服务器上。我们把它放到/home/iso/rhel5u2/ks目录下。即该文件的NFS访问路径为:

nfs:192.168.1.51:/home/iso/rhel5u2/ks/ks.cfg

其次,我们需要让安装程序知道我们希望它用kickstart方式安装,并告知它可以从哪里获得kickstart配置文件。这可以通过给内核添加一个参

数"ks=kickstart配置文件路径"来实现。我们只需对启动服务器上的default文件做一些小修改就可以做到这点:

LABEL rhel5u2-i386
KERNEL vmlinuz-rhel5u2-i386
APPEND ks=nfs:192.168.1.51:/home/iso/rhel5u2/ks/ks.cfg initrd=initrd-rhel4u2-i386.img
ramdisk_size=8192

这样在启动安装程序的时候,参数ks=nfs:192.168.1.51:/home/iso/rhel5u2/ks/ks.cfg会被传递给它,告诉它使用这个文件作为kickstart配置文件

来进行kickstart安装。

Linksys WRH54G 刷 DD-WRT 小记

在上网无意中发现,我的路由原来也是很能大的(和tp的402M比,哈哈),居然人在刷DD-WRT成功.
心中不安,我来试试,下载了新固件后,安全升级成功.上图
uploads/200909/04_124944_ddwrt.jpg

多了好多专业级路由的功能,其中比较有意思的,比如,无线中继(就是路由可以连接到别人的无线网,自己用)
还有QOS,不过番茄版的QOS更好,我这个刷不了,还有连接状态(看现在都谁在和你连接,有人功击你时就很有用),封P2P类的软件,由于是linux的内核,系统集成了相关功能插件.等无数功能,爽呆了.下面是改连接数的方法,telnet连接
DD-WRT v24 micro (c) 2008 NewMedia-NET GmbH
Release: 02/15/08 (SVN revision: 9063)

DD-WRT login: root
Password:
==========================================================

____ ___ __ ______ _____ ____ _ _
| _ | _ / / _ _ _| __ _|___ | || |
|| | || ||____ / / /| |_) || | / / __) | || |_
||_| ||_||_____ V V / | _ < | | V / / __/|__ _|
|___/|___/ _/_/ |_| _|_| _/ |_____| |_|

DD-WRT v24
http://www.dd-wrt.com

==========================================================

BusyBox v1.9.0 (2008-02-15 19:49:04 CET) built-in shell (ash)
Enter 'help' for a list of built-in commands.

u@h:w$ nv ^H^H^[[D^H^H
-sh: nv: not found
u@h:w$ nvram set ip_conntrack_max=4096
u@h:w$ nvram commit
nvram_commit(): end
u@h:w$

==========================================================

发现这个版本的固件有打不到某些网站的毛病,比如淘宝和新浪,双升级了一次固件
Router NameTP-LINK
Router ModelLinksys WRH54G
Firmware VersionDD-WRT v24-sp1 (07/27/08) micro – build 10012
现在好了,暂时还没发现问题

DOTA 互通 作弊 原理

Return Bug+GameCache的应用

一、排除泄露

在讲解完Return Bug的原理以及跟GameCache的简单应用后,我并没有进一步讲解更复杂的数据绑定,而是穿插讲了一篇中级教程《JASS动态注册事件》,因为在用Return Bug+GameCache写一些复杂的系统时,经常会用到动态注册事件。

但在讲解动态注册事件时,一个很重要的内容没有被提到,那就是排除在销毁触发器时由触发器条件和动作引起的泄露。不过在排泄时必须用到Return Bug+GameCache,因此我把排泄留到这章讲,当作Return Bug+GameCache的一个应用实例。

  好吧,让我们先回顾下动态注册事件,依旧用Tiveone的经典教程

 

jass: Copy code
//当触发注册的事件时调用的函数
function OnUnitAmort takes nothing returns nothing
//设置触发单位为无敌
call SetUnitInvulnerable( GetTriggerUnit(), true )
//破坏这个触发器,即下面的RegisterUnitAmortEvent所创建的触发器
//这样就不会导致该触发被多次调用,并且还能清理该触发所占用的内存
call DestroyTrigger(GetTriggeringTrigger())
endfunction

//注册模板
function RegisterUnitAmortEvent takes unit witchUnit returns nothing
//创建一个触发器
local trigger rTrg = CreateTrigger()
//为创建的触发器注册事件:当单位witchUnit的生命值小于或等于50的时触发事件
call TriggerRegisterUnitLifeEvent( rTrg , witchUnit, LESS_THAN_OR_EQUAL, 50 )
//注册触发器事件响应后所调用的函数
call TriggerAddAction( rTrg, function OnUnitAmort )
endfunction

这样的写法不是很好,它会造成内存泄露。我们来看下TriggerAddAction这个函数
native TriggerAddAction takes trigger whichTrigger, code actionFunc returns triggeraction

这里先生成了一个triggeraction,然后把它添加给了触发器;而当我们删除触发器的时候,这个triggeraction却并没有被删除。

那么,为了维护这世界的爱与正义,我们来排除上面动态注册事件的泄露吧~

首先,准备好下列Return Bug常用函数

jass: Copy code
function H2I takes handle h returns integer
return h
return 0
endfunction

function I2TG takes integer i returns trigger
return i
return null
endfunction

function I2TC takes integer i returns triggercondition
return i
return null
endfunction

function I2TA takes integer i returns triggeraction
return i
return null
endfunction

然后,上面的动态注册事件可以这样写

jass: Copy code
function RegisterUnitAmortAction takes nothing returns nothing
local trigger trg = GetTriggeringTrigger()
local triggeraction Act=I2TA(GetStoredInteger(udg_GC,I2S(H2I(trg)),"Triggeraction"))
call SetUnitInvulnerable(GetTriggerUnit(), true)
call TriggerRemoveAction(trg,Act)
call DestroyTrigger(trg)
call FlushStoredMission(udg_GC,I2S(H2I(trg)))
set trg = null
set Act=null
endfunction

function RegisterUnitAmortEvent takes unit witchUnit returns nothing
local trigger trg = CreateTrigger()
local triggeraction Act
call TriggerRegisterUnitStateEvent(trg, witchUnit, UNIT_STATE_LIFE, LESS_THAN_OR_EQUAL, 50)
set Act=TriggerAddAction(trg,function RegisterUnitAmortAction)
call StoreInteger(udg_GC,I2S(H2I(trg)),"Triggeraction ",H2I(Act))
set trg = null
set Act=null
endfunction

在这里,我们定义了一个触发器动作变量Act,用它来保存生成的触发器,然后把它删除;大家是不是觉得这种方法似曾相识呢——以前我们排除点泄露的时候,也是用个点变量来保存生存的点,之后再清除这个变量保存的点。在删除点时,我们使用 RemoveLocation( )函数;而删除触发器条件或动作,我们使用TriggerRemoveCondition()和TriggerAddAction()这两个函数。(至于TriggerClearActions()和TriggerClearConditions()这两个函数,老狼说是废函数,“相当于把垃圾扫床底下”,那我们就不去理会它们吧。)

触发器条件和动作的清除的确比较麻烦,不过大家可以采用老狼写的两个删除触发器自定义函数:

jass: Copy code
function DestroyTriggerAllById takes integer t returns nothing
call TriggerRemoveCondition(I2TG(t),I2TC(GetStoredInteger (udg_GC,I2S(t),"TriggerCondition")))
call DestroyTrigger(I2TG(t))
call FlushStoredMission(udg_GC,I2S(t))
endfunction

function DestroyTriggerAll takes trigger trg returns nothing
call TriggerRemoveCondition(trg,I2TC(GetStoredInteger(udg_GC,I2S(H2I(trg)),"TriggerCondition")))
call DestroyTrigger(trg)
call FlushStoredMission(udg_GC,I2S(H2I(trg)))
endfunction
//========================================================
function RegisterUnitAmortCond takes nothing returns nothing
call SetUnitInvulnerable(GetTriggerUnit(), true)
call DestroyTriggerAll(GetTriggeringTrigger())
endfunction

function RegisterUnitAmortEvent takes unit witchUnit returns nothing
local trigger trg = CreateTrigger()
call TriggerRegisterUnitStateEvent(trg, witchUnit, UNIT_STATE_LIFE, LESS_THAN_OR_EQUAL, 50)
call StoreInteger(udg_GC,I2S(H2I(trg)),"TriggerCondition",H2I (TriggerAddCondition(trg,Condition(function RegisterUnitAmortCond))))
set trg = null
endfunction

老狼把触发器动作里的内容写到了条件里,为什么这样写大家可以去搜索教程,这里就不赘述了。这里DestroyTriggerAll()和DestroyTriggerAllById()两个函数区别仅仅在于一个传递触发器类型参数,一个传递整数类型参数(这里的整数参数是通过H2I(trg)得到的) ,大家按自己写JASS的习惯,选择其中一个来使用就可以了。此外,为了详细讲解步骤,我定义了Act这个触发器动作变量,但实际写代码时,可以像老狼那样省略这个中间变量,直接把数据存入缓存。
大家不妨以老狼这段代码,作为动态注册事件的模板。

二、缓存的使用

在之前讲解缓存时,我曾说Return Bug改变了GameCache的命运,发掘了GameCache的潜力;那么GameCache究竟强大在哪里。此外,当被问到什么是GameCache,高手们往往会回答,“一个数据库”、“一个仓库”。GameCache是如何担当存储数据的重任呢,我们不妨看下GameCache与全局变量的对比。

1.单个变量

我们要储存一个单位,比如everguo,

数据
GameCache
全局变量

Everguo(单位)
StoreInteger(udg_GC,”Handsome”,”Everguo”,H2I(Everuo))
Set Handsome=Everguo

(Handsome为单位型全局变量)

2.数组

数据
GameCache
全局变量

1 Everguo

2 汤姆.汗克斯

3 莱昂纳多

StoreInteger(udg_GC,”Handsome”,”1”,H2I(Everuo))

StoreInteger(udg_GC,”Handsome”,”2”,H2I(汤姆.汗克斯))

StoreInteger(udg_GC,”Handsome”,”3”,H2I(莱昂纳多))

Set Handsome[1]=Everguo

Set Handsome[2]=汤姆.汗克斯

Set Handsome[3]=莱昂纳多

(Handsome为单位型全局变量数组)

3.多个数组

数据
GameCache
全局变量

1
2
StoreInteger(udg_GC,”Handsome”,”1”,H2I(Everuo))

StoreInteger(udg_GC,”Handsome”,”2”,H2I(汤姆.汗克斯))

StoreInteger(udg_GC,”Handsome”,”3”,H2I(莱昂纳多))

StoreInteger(udg_GC,”SeLang”,”1”,H2I(Red_Wolf))

StoreInteger(udg_GC,”SeLang”,”2”,H2I(幽灵狼))

StoreInteger(udg_GC,”SeLang”,”3”,H2I(田伯光))

Set Handsome[1]=Everguo

Set Handsome[2]=汤姆.汗克斯

Set Handsome[3]=莱昂纳多

Set SeLang[1]= Red_Wolf

Set SeLang[2]= 幽灵狼

Set SeLang[3]= 田伯光

(Handsome、SeLang均为单位型全局变量数组)

1 Everguo

2 汤姆.汗克斯

3 莱昂纳多

1 Red_Wolf

2 幽灵狼

3 田伯光

以上是GameCache和全局变量在储存数据上的对比,看上去GameCache储存数据比全局变量繁琐得多;不知大家注意到没有,GameCache跟全局变量相比有个最大的优点——能动态地生成数据库。

比如,在游戏开始后,我们想再储存如下人妖排行榜:

1 东方不败

2 李宇春

3 看帖不回的

用GameCache能轻易做到

jass: Copy code
StoreInteger(udg_GC,”RY”,”1”,H2I(东方不败))

StoreInteger(udg_GC,”RY”,”2”,H2I(李宇春))

StoreInteger(udg_GC,”RY”,”3”,H2I(看帖不回的))

但用全局变量却做不到,除非我们一开始就定义了“RY”这个单位型全局变量数组。

回想起来,之前我们为什么说JASS不能用T替代,因为Return Bug+GameCache在T里无法做到。比如,在上文排除触发器泄露中,call StoreInteger(udg_GC,I2S(H2I(trg)),"Triggeraction ",H2I(Act)),如果把这条语句用全局变量来写,那么我们必须事先定义好一个触发器动作型全局变量数组;如果我们想用全局变量绑定数据,那得预先定义海量的全局变量数组。

此外,GameCache的灵活性也是无可替代,以下是上次教程讲解Return Bug+GameCache绑定数据时提到例子

jass: Copy code
function ManData takes unit man,integer stature,integer avoirdupois returns nothing
call StoreInteger(udg_GC,I2S(H2I(man)),"stature",stature)
call StoreInterger(udg_GC,I2S(H2I(man)),"avoirdupois",avoirdupois)
endfunction

然后

jass: Copy code
call ManData(Lucy,165,45)
call ManData(Jack,172,60)

将数据输入。可以看出,只需预先写个系统(比如上文的ManData函数) ,然后再向缓存写入数据就非常方便而且一目了然。

那么,用全局变量的话,如何做到呢

set stature[1]=165
set stature[2]=172
set avoirdupois[1]=45
set avoirdupois[2]=65

首先定义了stature和avoirdupois这两个全局变量数组后,我们还必须有惊人的记忆力,记住数组方括号内的数字对应的单位——这里1对应Lucy,2对应Jack,如果单位多了将很难区分;而缓存在记录数据时,是以字符窜为标识,很形象,比如我们称呼一个人,是称呼“9527”呢,还是“华安”。
缓存与全局变量数组的区别就在于此,它们各有优缺点。缓存以字符窜为标识,存储数据,这在我们写代码的时候能一目了然;但这也正是它的缺点,写入和读出数据速度比较慢。全局变量数组虽然不形象,难记忆,但效率高。
在这里还是向大家推荐缓存,虽然它效率不如全局变量高,但在游戏中差别不大;我们也没必要为提高一点点效率而牺牲代码的可读性。

此外,GameCache还可储存二维数组,比如上文的三个排行榜:

排行榜

排名

1
2
3

1
Everguo
Red_Wolf
东方不败

2
汤姆.汗克斯
幽灵狼
李宇春

3
莱昂纳多
田伯光
看帖不回的

把上面数据写入

jass: Copy code
StoreInteger(udg_GC,”1”,”1”,H2I(Everuo))
StoreInteger(udg_GC,”1”,”2”,H2I(汤姆.汗克斯))
StoreInteger(udg_GC,”1”,”3”,H2I(莱昂纳多))
StoreInteger(udg_GC,”2”,”1”,H2I(Red_Wolf))
StoreInteger(udg_GC,”2”,”2”,H2I(幽灵狼))
StoreInteger(udg_GC,”2”,”3”,H2I(田伯光))
StoreInteger(udg_GC,”3”,”1”,H2I(东方不败))
StoreInteger(udg_GC,”3”,”2”,H2I(李宇春))
StoreInteger(udg_GC,”3”,”3”,H2I(看帖不回的))

然后我们写个函数方便查找数据

jass: Copy code
function UnitData takes integer x,integer y returns unit
return I2U(GetStoredInteger(udg_GC,I2S(x),I2S(y)))
endfunction

如果我们想调用这个二维数组(2,2)对应的单位,只需set unit=UnitData(2,2),就把幽灵狼赋值给了unit。

在T中只有一维数组,因此在处理很多问题时极不方便。而在使用GameCache后,我们可以StoreInteger(udg_GC,I2S(H2I(xx)), I2S(H2I(xx)),H2I(xx))或是GetStoredXXXX(udg_GC,I2S(H2I(xx)),I2S(H2I(xx))),要多方便有多方便。

或许此刻你已经在心中呐喊“Return Bug+GameCache”实在是太YD了,的确,我以前就把他们比喻成奸夫淫妇来着~

不得不说,Return Bug+GameCache改变了WEer写代码的思维,灵活地运用它们我们可以写出很多实用的系统。
或许上面关于Return Bug+GameCache替代全局变量存储数据的例子你不是很懂,不要紧,看完下面的演示你将对Return Bug+GameCache的使用有更清晰的认识。

三.Return bug+GameCache+JASS动态注册事件实例

演示永远是最好的教程。那么,在学习了JASS动态注册事件,以及用Return bug+GameCache存储数据后,我们来看个实例。
大多数RPG地图都有这样的T——“当单位进入XX区域,立刻移动单位到XX区域”,比如常见的进洞,当英雄进入洞口,立刻被传送到洞内,再从洞内的出口出来。下面是我写的一个3C地图的进洞函数。

jass: Copy code

function H2I takes handle h returns integer
return h
return 0
endfunction
function I2U takes integer i returns unit
return i
return null
endfunction

function Trig_RectUnitMove_Conditions takes nothing returns boolean
local unit hero = GetTriggerUnit() //获得触发单位
local trigger trig = GetTriggeringTrigger() //获得当前触发
local player P = GetOwningPlayer(hero)
local real x = GetStoredReal(udg_GC,I2S(H2I(trig)),"RectUnitMoveX") //从缓存中读出目标区域中心的X坐标
local real y = GetStoredReal(udg_GC,I2S(H2I(trig)),"RectUnitMoveY") //从缓存中读出目标区域中心的Y坐标
local integer level = GetStoredInteger(udg_GC,I2S(H2I(trig)),"RectUnitMoveLevel") //从缓存中读出英雄等级限制
local integer i=0
if IsUnitType(hero, UNIT_TYPE_HERO) != true or (GetPlayerId(P)>11) then //如果触发单位不是英雄,或触发玩家是中立玩家
set hero=null
set

trig=null
return false //直接返回,不执行下面的动作
endif
set i = GetHeroLevel(hero) //获得英雄等级
if i<level then
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 10, "英雄等级未满"+I2S(level)+"级,不能进入")
//英雄等级不够,不能进洞
else
call SetUnitX(hero,x)
call SetUnitY(hero,y) //移动英雄到目标区域中心
call PanCameraToTimedForPlayer(P,x,y,0) //镜头跟随
call IssueImmediateOrderById(hero,OrderId("stop"))
//由于用坐标函数移动单位,单位当前状态不变,因此进洞后会继续移动,所以得让它停下来
endif
set hero=null
set trig=null
return false
endfunction

function RectUnitMoveTrigger takes integer level,rect r1,rect r2 returns nothing
local real x = GetRectCenterX(r2) //获得目标区域中心的X坐标
local real y = GetRectCenterY(r2) //获得目标区域中心的Y坐标
local trigger trig=CreateTrigger()
call StoreReal(udg_GC,I2S(H2I(trig)),"RectUnitMoveX",x) // 储存目标区域中心的X坐标
call StoreReal(udg_GC,I2S(H2I(trig)),"RectUnitMoveY",y) // 储存目标区域中心的Y坐标
call StoreInteger(udg_GC,I2S(H2I(trig)),"RectUnitMoveLevel",level) //存储英雄等级限制
call TriggerRegisterEnterRectSimple( trig, r1 ) //以单位进入指定区域为事件
call TriggerAddCondition(trig,Condition(function Trig_RectUnitMove_Conditions)) //添加条件
set trig = null
endfunction

上面是个很简单的Return bug+GameCache+JASS动态注册事件运用的例子,在学习了前面Return bug原理教程的朋友很容易能看懂,需要说明的是,这里使用Return bug+GameCache绑定数据,没用把目标区域(r2)中心坐标和等级限制绑定在指定区域(r1),而是绑定在了新生成的触发器(trig)上,因为我们可以通过GetTriggeringTrigger()来得到当前的触发,却不能得到当前英雄所在的区域(r1)。此外,我们在绑定数据的时候,除了触发器,一般是跟单位或计时器绑定,然后通过GetTriggerUnit()和GetExpiredTimer()分别获得单位和计时器,然后从单位和计时器上读出预先绑定的数据。
从上文的例子可以看出,我们先把目标区域中心的坐标写到缓存里,保存在“I2S(H2I(trig))”下,然后通过local trigger trig = GetTriggeringTrigger()来获得当前触发,用GetStoredReal(udg_GC,I2S(H2I(trig)),"XXXXXX")来读出数据。(原理我就不复述了,参看前面Return bug原理教程。)
(给十分钟,好好看下这段代码。)
相信你已经明白了,所谓的数据绑定,无非是把数据用Return bug+GameCache把数据存储到缓存中“XXX”的类别名下(这里的类别“XXX”,大都是通过I2S(H2I())将触发器、单位和计时器转换得来的),然后在按上文的方法从缓存读出来。
那么,我们为何要称这方法为数据绑定呢?
在讲解Return bug原理的时候,我曾提了两种存储数据的方法,一是上文的以I2S(H2I())转化的handle类参数为类别名,如

jass: Copy code
call StoreReal(udg_GC,I2S(H2I(trig)),"RectUnitMoveX",x)
call StoreReal(udg_GC,I2S(H2I(trig)),"RectUnitMoveY",y)
call StoreInteger(udg_GC,I2S(H2I(trig)),"RectUnitMoveLevel",level)

一是以I2S(H2I())转化的handle类参数为缓存项目名

jass: Copy code
call StoreReal(udg_GC,"RectUnitMoveX",I2S(H2I(trig)),x)
call StoreReal(udg_GC,"RectUnitMoveY",I2S(H2I(trig)),y)
call StoreInteger(udg_GC,"RectUnitMoveLevel",I2S(H2I(trig)),level)

我曾说,第二种方法,不合我们的习惯,为何?
比如,我们希望这个触发器在运行后自动销毁,此时我们应当将缓存中的数据也清除掉。
以I2S(H2I())转化的handle类参数为类别名的清除缓存数据

jass: Copy code
call FlushStoredMission(udg_GC,I2S(H2I(trig)))

以I2S(H2I())转化的handle类参数为缓存项目名的清除缓存数据

jass: Copy code
FlushStoredReal(udg_GC,"RectUnitMoveX",I2S(H2I(trig)))
FlushStoredReal(udg_GC,"RectUnitMoveY",I2S(H2I(trig)))
FlushStoredInteger(udg_GC,"RectUnitMoveLevel",I2S(H2I(trig)))

比较上面两种方法,大家应该明白了为何我们要以I2S(H2I())转化的handle类参数为类别名了吧。用这种方法,可以很容易的把数据与handle类参数挂钩,也可很容易地清除,因此我们称呼这种方法为数据绑定。

当我们把数据绑定到一个单位上,比如以前那个仿暗黑佣兵系统,当单位嗝屁后,可以把与它相关的数据清理掉,释放内存;把数据绑定在触发器上,比如那个环绕函数模板,当环绕时间到了或是释放技能的英雄挂了后,要立刻销毁计时器,同时清空缓存;在前面讲解动态注册事件排泄时,我们看到了,在删除触发器后,也有清除缓存数据的语句。
这便是数据绑定,也是JASS强大所在;为了让大家印象深刻,我再举个例子。

如果我们想只让特定类型单位进入区域才触发事件,比如3C里羊进圈选英雄,那么我们只需修改下上面的代码

jass: Copy code

function Trig_WC_Conditions takes nothing returns boolean
local unit hero = GetTriggerUnit() //获得触发单位
local trigger trig = GetTriggeringTrigger() //获得当前触发
local player P = GetOwningPlayer(hero)
local real x = GetStoredReal(udg_GC,I2S(H2I(trig)),"RectUnitMoveX") //从缓存中读出目标区域中心的X坐标
local real y = GetStoredReal(udg_GC,I2S(H2I(trig)),"RectUnitMoveY") //从缓存中读出目标区域中心的Y坐标
local integer WCuid = GetStoredInteger(udg_GC,I2S(H2I(trig)),"WCuid") //从缓存中读出指定单位类型
local integer uid=GetUnitTypeId(hero)
local string s=GetStoredString(udg_GC,I2S(H2I(trig)),"String")
if WCuid!=uid then
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 10, s) //与指定单位类型不匹配,不能入内
else
call SetUnitX(hero,x)
call SetUnitY(hero,y) //移动单位到目标区域中心
call PanCameraToTimedForPlayer(P,x,y,0) //镜头跟随
call IssueImmediateOrderById(hero,OrderId("stop"))
//由于用坐标函数移动单位,单位当前状态不变,因此进洞后会继续移动,所以得让它停下来
endif
set hero=null
set trig=null
return false
endfunction

function WCMoveTrigger takes integer uid,rect r1,rect r2,string s returns nothing
local real x = GetRectCenterX(r2) //获得目标区域中心的X坐标
local real y = GetRectCenterY(r2) //获得目标区域中心的Y坐标
local trigger trig=CreateTrigger()
call StoreReal(ud

g_GC,I2S(H2I(trig)),"RectUnitMoveX",x) // 储存目标区域中心的X坐标
call StoreReal(udg_GC,I2S(H2I(trig)),"RectUnitMoveY",y) // 储存目标区域中心的Y坐标
call StoreInteger(udg_GC,I2S(H2I(trig)),"WCuid",uid) //存储进入区域单位类型
call StoreString(udg_GC,I2S(H2I(trig)),"string",s) //存储提示文字
call TriggerRegisterEnterRectSimple( trig, r1 ) //以单位进入指定区域为事件
call TriggerAddCondition(trig,Condition(function Trig_WC_Conditions)) //添加条件
set trig = null
endfunction

上面代码使以单位类型判断替换英雄等级判断,只有特定单位才能进入区域;类似地,你也可以加入单位判断,只有XX单位才能进入,比如“只有FRJJ才能进入看帖不回的人的房间”,只需StoreReal(udg_GC,I2S(H2I(trig)),"Lover",FRJJ),然后比较触发单位是不是FRJJ,这里就不把演示写出来了。

相信通过上面的例子,你已经对Return bug+GameCache有一定了解了,但那是不够的,在下次的教程,我将讲解如何用Return bug+GameCache做更复杂的系统和演示。

BCC工具的使用:
1. 运行bcc.bat
2. 然后将你修改过的地图中的J文件和原正常地图中的J文件复制到软件目录, 比如我的修改过的地图名为 war3map.j 原始未修改的J文件为 war3map_o.j.
3. 在命令行敲入 bcc war3map_o.j war3map.j 如果提示" 恭喜, 生成成功"字样时则为成功, 软件目录中会生成一个new_war3map.j文件,将这个new_war3map.j重命名为war3map.j替换正版地图中的J文件即可.

功能:
1. 可以使作弊地图拥有和正规地图相同的HASH值. 即你使用的是作弊图, 而主机使用的是正规图, 你不会因为地图不同而下载地图.

注意: J文件并不是所有东西都可以改, 引用 Sc2DotA.CoM 的 Thewisp (目前的57c作弊版作者) 一段话:

凡是实体数据都不能改,例如触发,timer,等等所有类型为handle的东西

整数,实数,boolean,字符串等都可以,此外缓存也可以操作。

原理是把缓存单方修改后,用sync系列函数把数据扩散出去,因此他就是合法数据了

点击下载

win 2008 自动 多网卡 负载 带宽叠加

用了几个月windows2008 server 了,今天有个新发现,原来xp中,如果你有双线接入,并正确设置了ip,xp系统也只会选择一条线路来用,但是2008就不同了,2008有NLB,也就是说如果你有多条链路,他会一起来用,下面是只启用了一条线路
uploads/200908/26_151151_1.jpg

下面是启用了一个局域网和一个无线网之后的情况

uploads/200908/26_151313_2.jpg
uploads/200908/26_151318_4.jpg

刚刚入手 威盛EPIA-933AFIC17*17 MINI 主板

型号.Epia-933AFIC VIA OEM给iiyama的.
尺寸16.9CMx16.9CM
整夜不关机下载服务器的首选.非常低能耗.
主板内嵌带VIA C3 933 Mhz CPU
带声卡网卡显卡USB等.一个PCI slot.2个SD内存插槽.
这东西十分省电哟,具体有多省,这机子全套满载也就40W
如果当路由用也就15W

Via Epia系列的功率计算器http://www.mini-box.com/site/mb/Power_MB.htm

bash 文件处理操作工具总结

bash 文件处理操作工具总结

1 常用过滤器
1.1 tr
可以把tr看成是sed的一个简化版本,它可以用一个字符来替换另一个字符,或者去除一些字符。也可以用来去除重复字符。tr主要用于删除文件中控制字符或进行字符转换。语法:
tr -c -d -s ["string1_to_translate_from"] ["string2_to_translate_to"] < input-file>
-c 用字符串1中字符集的补集替换此字符集,要求字符集为ASCII。
-d 删除字符串1中所有输入字符。
-s 删除所有重复出现字符序列,只保留第一个;即将重复出现字符串压缩为一个字符串。
字符范围
指定字符串1或字符串2的内容时,只能使用单字符或字符串范围或列表。
[a-z] a-z内的字符组成的字符串。
[A-Z] A-Z内的字符组成的字符串。
[0-9] 数字串。
octal 一个三位的八进制数,对应有效的ASCII字符。
[O*n] 表示字符O重复出现指定次数n。因此[O*2]匹配OO的字符串。
tr中特定控制字符的不同表达方式
速记符含义八进制方式
a Ctrl-G 铃声07
b Ctrl-H 退格符10
f Ctrl-L 走行换页14
n Ctrl-J 新行12
r Ctrl-M 回车15
t Ctrl-I tab键11
v Ctrl-X 30
例1:删除文件中重复的小写字母,双引号是必须的
[root@redhat test]# cat new
aaabbbZZZBBBcccDDD
abcabcabcAABBCC
[root@redhat test]# cat new|tr -s "[a-z]"
abZZZBBBcDDD
abcabcabcAABBCC

例2:删除空行
[root@redhat test]# cat new
aaabbbZZZBBBcccDDD

abcabcabcAABBCC
[root@redhat test]# tr -s "[12]"<new
aaabbbZZZBBBcccDDD
abcabcabcAABBCC

例3:将大写转成小写
[root@redhat test]# tr "[A-Z]" "[a-z]"<new
aaabbbzzzbbbcccddd

abcabcabcaabbcc

例4:将字母以外的字符转换成新行,并删除重复的
[root@redhat test]# cat new
aa1ab3bbZ4ZZB5B676BcccDDD
567456234234
23423425
abcabcabcAABBCC
[root@redhat test]# tr -cs "[A-Za-z]" "[n*]"<new
aa
ab
bbZ
ZZB
B
BcccDDD
abcabcabcAABBCC
如果把-s去掉重复行去掉,就会成这个样子
[root@redhat test]# tr -c "[A-Za-z]" "[n*]"<new
aa
ab
bbZ
ZZB
B

BcccDDD

abcabcabcAABBCC

例5:把/etc/passwd中的:换成TAB
[root@redhat test]# tr "[:]" "t" </etc/passwd
root x 0 0 root /root /bin/bash
bin x 1 1 bin /bin /sbin/nologin
daemon x 2 2 daemon /sbin /sbin/nologin
adm x 3 4 adm /var/adm /sbin/nologin
lp x 4 7 lp /var/spool/lpd /sbin/nologin
sync x 5 0 sync /sbin /bin/sync
…..

例6:使内容更具可读性
[root@redhat test]# echo $PATH | tr ":" "n"
/usr/local/sbin
/usr/local/bin
/sbin
/bin
/usr/sbin
/usr/bin
/usr/X11R6/bin
/root/bin
/root/Testsh

例7:在vi 中使用
1,$!tr -d 'a'

1.2 wc 显示行数,单词数,字节数,字符数
参数:
–byte    -c  仅仅显示输入中的字节数
–lines    -l  仅仅显示输入中的行数
–max-line-length  -L  显示输入中最长的行的长度
–chars    -m  仅仅显示输入中的字符数
–words    -w  仅仅显示输入中的单词数
一个单词是指由空格,TAB,换行或它们的混合分隔限定的一系列字符。
1.3 uniq 显示唯一的行
语法:uniq [options][input-file][output-lile]
–count  -c  在行首显示该行在输入文件中出现的次数
–repeated  -d  显示一次重复出现的行,不显示没有重复出现的行
–skip-fields=nfield    -f nfield  忽略每行的前n个邮空白字符分隔出的字段
–ignore-case  -i  比较行时忽略字符大小写
–skip-chars=nchar    -s nchar  忽略每行的前n个字符。如果同时使用了–skip-nfields选项,uniq将忽略行首的n个字段以及它们后面的n个字符。可以使用该选项来忽略字段打头的空白字符
–unique  -u  仅显示那些没有重复出现的行
–check-chars=nchar  -w nchar  在应用-f 与-s选项之后,一共比较行中n个字符。默认情况下uniq将比较整行。
例:
[root@redhat test]# cat 98
i am zb
i am zb
i am zb
fuck you
he is sb
he is sb
he is sb
he is sb
he is sb
he is sb
he is sb
[root@redhat test]# uniq 98
i am zb
fuck you
he is sb
#去掉重复出现的行
[root@redhat test]# uniq -d 98
i am zb
he is sb
#显示一次重复出现的行,没重复的不显示
[root@redhat test]# uniq -u 98
fuck you
#仅显示不重复的行
[root@redhat test]# uniq -c 98
3 i am zb
1 fuck you
7 he is sb
#只显示一次重复出现的行,并统计出数次数

1.4  grep 在文件中搜索模式
语法:grep [options] pattern [file-list]
主要选项
-E  可使用扩展正则表达式与egrep相同
-F  解释为固定的字符串,与fgrep同
-G  解释为基本正则表达式。默认值
其它选项
–count  -c  只显示每个文件中包含匹配的行的数目
–context    -Cn  对每个匹配的行显示n行上下文
–file=file    -f file  该文件中每行都包含一个模式,从输入中找匹配每个模式的行
–no-filename    -h  当搜索多个文件时,在每行的开始不显示文件名
–ignore-case  -i  忽略大小写
–files-with-matches  -l  仅显示包含匹配的文件名,仅显示一次
–max-count=n  -m n    显示包含匹配的n行后停止读取文件或标准输入
–line-number    -n  在显示的每行前显示行号
–quiet  -q  不发送任何内容到标准输出,仅设置退出代码
–recursive  -r或-R  递归处理目录中的所有文件
–no-message    -s  如果文件不存在或不可读,不显示错误消息
–invert-match    -v  显示不包含匹配的行,反选
–word-regxp    -w  必须匹配整个字
–line-regxp    -x  必须匹配整行

1.5 sort 对文件排序或合并
语法:sort [options][file-list]
-b  忽略行开头的空格或TAB
-c  检查文件是否被恰当地排序。如以已排好则不显示任何消息,否则返回退出状态为1
-d  忽略除字母数字和空白符外的所有其他字符。例如标点符号
-f  将所有小写字母看作是大写字母进行比较。
-i  忽略所有的非打印字符
-k start[,stop]  按指定的排序字段进行排序
-m  如输入多个文件,不检查文件是否排好序而直接将它们全并起来
-n  按算术序列排序
-o filename  将输出发送到filename,filename可以是file-li

st中某个文件
-r  按逆序排列
-t x  指定字段分隔符为x
-u  对重复行仅输出一次
例1:
[root@redhat Testsh]# cat cars
plym fury 1970 73 2500
chevy malibu 1990 60 3000
ford mustang 1965 45 10000
volvo s80 1998 102 9850
ford thundbd 2003 15 10500
chevy malibu 2000 50 3500
bmw 325i 1985 115 450
honda accord 2001 30 6000
ford taurus 2004 10 17000
toyota rav4 2002 180 750
chevy impata 1985 85 1550
ford explor 2003 25 9500
[root@redhat Testsh]# sort -n -k5 cars
bmw 325i 1985 115 450
toyota rav4 2002 180 750
chevy impata 1985 85 1550
plym fury 1970 73 2500
chevy malibu 1990 60 3000
chevy malibu 2000 50 3500
honda accord 2001 30 6000
ford explor 2003 25 9500
volvo s80 1998 102 9850
ford mustang 1965 45 10000
ford thundbd 2003 15 10500
ford taurus 2004 10 17000
按数字方式给第5个字段从小到大排序

例2:
[root@redhat Testsh]# sort -t ":" -k3 -nr /etc/passwd
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
root5:x:559:0:shashijie:/home/root:/bin/bash
root4:x:558:0:shashijie:/home/root:/bin/bash
root3:x:557:0:shashijie:/home/root:/bin/bash
root2:x:556:0:shashijie:/home/root:/bin/bash
root1:x:555:0:shashijie:/home/root:/bin/bash
ssj5:x:554:554:shashijie:/home/ssj:/bin/bash
ssj4:x:553:553:shashijie:/home/ssj:/bin/bash
ssj3:x:552:552:shashijie:/home/ssj:/bin/bash
ssj2:x:551:551:shashijie:/home/ssj:/bin/bash
ssj1:x:550:550:what,beijing,12345678,123123:/home/ssj:/bin/bash
test1:x:501:501:testmod:/home/test1:/bin/bash
ssj:x:500:500:shashijie:/home/ssj:/bin/bash
nobody:x:99:99:Nobody:/:/sbin/nologin
desktop:x:80:80:desktop:/var/lib/menu/kde:/sbin/nologin
pcap:x:77:77::/var/arpwatch:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
webalizer:x:67:67:Webalizer:/var/www/html/usage:/sbin/nologin
smmsp:x:51:51::/var/spool/mqueue:/sbin/nologin
apache:x:48:48:Apache:/var/www:/sbin/nologin
mailnull:x:47:47::/var/spool/mqueue:/sbin/nologin
xfs:x:43:43:X Font Server:/etc/X11/fs:/sbin/nologin
gdm:x:42:42::/var/gdm:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
rpm:x:37:37::/var/lib/rpm:/bin/bash
rpc:x:32:32:Portmapper RPC user:/:/sbin/nologin
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
nscd:x:28:28:NSCD Daemon:/:/sbin/nologin
postgres:x:26:26:PostgreSQL Server:/var/lib/pgsql:/bin/bash
named:x:25:25:Named:/var/named:/sbin/nologin
squid:x:23:23::/var/spool/squid:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
news:x:9:13:news:/etc/news:
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
halt:x:7:0:halt:/sbin:/sbin/halt
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
sync:x:5:0:sync:/sbin:/bin/sync
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
root:x:0:0:root:/root:/bin/bash
以:为分隔符,按数字的方式给第3个字段进行反向排序(从大到小)

例3:
[root@redhat Testsh]# sort -nb -k3.2 cars
chevy malibu 2000 50 3500
honda accord 2001 30 6000
toyota rav4 2002 180 750
ford explor 2003 25 9500
ford thundbd 2003 15 10500
ford taurus 2004 10 17000
ford mustang 1965 45 10000
plym fury 1970 73 2500
bmw 325i 1985 115 450
chevy impata 1985 85 1550
chevy malibu 1990 60 3000
volvo s80 1998 102 9850
以数字方式(-n)忽略之前的空字符(-b),从第3 个字段的第2个字符开始排序

例4:
[root@redhat Testsh]# sort -b -k5n -k1f cars
bmw 325i 1985 115 450
toyota rav4 2002 180 750
chevy impata 1985 85 1550
plym fury 1970 73 2500
chevy malibu 1990 60 3000
chevy malibu 2000 50 3500
honda accord 2001 30 6000
ford explor 2003 25 9500
volvo s80 1998 102 9850
ford mustang 1965 45 10000
ford thundbd 2003 15 10500
ford taurus 2004 10 17000
忽略前边的空字符,按第5个字段数字方法进行排序如果相同则再按第1个字段排序并不区分大小写

例5:
[root@redhat Testsh]# sort -b -k3,3 -k1 cars
ford mustang 1965 45 10000
plym fury 1970 73 2500
bmw 325i 1985 115 450
chevy impata 1985 85 1550
chevy malibu 1990 60 3000
volvo s80 1998 102 9850
chevy malibu 2000 50 3500
honda accord 2001 30 6000
toyota rav4 2002 180 750
ford explor 2003 25 9500
ford thundbd 2003 15 10500
ford taurus 2004 10 17000
忽略空字符,从第3 个字段的第1个字符开始到第3 个字段尾进行排序,如相同再按字段1 进行排序,如果不指定k3,3的末尾,将会比较从第3个字段到行的结束,则不会有相同的行,就不会进行第二次的排序。

注意:同时使用-u 与-f时有时会丢失行所以最好这样用
sort -u -k 1f -k 1 test

1.6 split 将文件分成几部分
语法:split [options][filename[prefix]]
-a len  指定创建文件名后缀的长度为len个字符。默认为2
-b n[u]  将输入分成n个字节长的几个文件。u为可选的单位 b,k,m
-l num  将输入分解为具有num行长的文件。默认为1000
split -b 200 cars

1.7 sed
http://www.kumouse.com/article.asp?id=106

1.8 gawk
http://www.kumouse.com/article.asp?id=104

1.9 aspell

1.10 cmp 比较两个文件

1.11 comm 比较经以排序的文件

1.12 cpio

1.13 cut 从输入行中选取字符或者字段
语法:cut [options][file-list]
-c clist    选取由clist中的列号指定的字符。(各值用,分隔。列范图用-n,n-,n-m来表示)
-d dchar    将dchar作为输入字段的分隔符。默认为TAB.
-f flist    选择flist指定的字段。
–output-delimiter=ochar    将ochar指定为输出字段分隔符。
例1:
[root@redhat Testsh]# ll |cut -c57-90|grep ^[a-zA-Z]
apue2.zip
awk_glarr
awk_if
awk_out
awk_t
awk_t1
cars
Fibonacci_recursive.sh
Fibonacci_while.sh
find_uid
fordfile
if.ak
manuf
Recursive.sh
report
text.txt
tmp.sh
word_usage
xaa
xab
xac
xad
显示第57-90列,并去除空白的行

1.14 diff 比较两个文件的不同

1.15 fmt 简单地格式化文本
语法:fmt [options][file-list]
-s  截断长行但不填充短行
-t  除每个段落第1行外,都缩进
-u  改变格式化输出使得字之间为一个空格,句子之间为两个空格
-w n  将输出的行宽度改为n个字符。不带该

选项,fmt输出行宽度为75个字符
例:fmt -w 50 memo
将文件memo的宽度改为50字符,并输入到标准输出

1.16 od 根据指定的格式输出文件内容 648

1.17 paste 将文件对应行连接起来
语法:paste[option][file-list]
-d dlist  dlist是用来分隔输出字段的字符列表。如果仅有一个字符,paste将使用该字符替换TAB作为字段分隔符,如包含多个字符,这些字符轮流使用。
-s  一次处理一个文件,水平连接。

1.17 pr 给文件标明页码,以供打印 654

1.18 strings 显示可打印字符串

Sed学习笔记

  sed [-n] program [file-list]
  sed [-n] -f program-file [file-list] 1.2参数
  略 1.3 选项
  –file program-file    -f program-file    指定文件中sed程序可以命令行上使用多次
  –in-place[=suffix]    -i [suffix]      就地编辑文件,把输出送到原来的文件中,并备份原来文件加后缀suffix
  –help                概述sed的用法
  –quiet或–silent    -n        除非使用print指令或标志来指定否则不会将文本行复制到标准输出 1.4 编辑器基础
  sed程序由符合如下语法的一行或多行命令构成
  [address[address]] instruction [argument-list]
  address是可选的,如省略,那么sed将对输入中的所有行进行处理
  instruction是用于改变文本的指令address用来选定行instruction来处理
  argument-list中参数的数目和类型取决于指令instruction
  如果想把多个sed命令放在同一行,可以使用;   1.4.1 地址
    行号作为地址可以用来选择某一行,$表示输入中的最后一行
    正则表达式作为地址,可以选中与之相匹配字符串的行
    sed可以使用除反斜杠和换行符之外的任意字符来定界
    如指定一个地址sed将选择该地址匹配行
    如指定二个地址,第一个地下选择行首,第二个选择匹配这下一行
  
  1.4.2 指令
    d    删除指令:导致sed不输出被选择行,并且不继续完成对该行的后续处理过程,sed执行删除后,它将从输入读取下一行,并从program或program-file中的第1条命令开始执行     n    下一条指令:输出当前选择的行,然后从输入中读下一行,并从program或program-file中的下一条命令开始对新读入的行进行处理     a    追加指令,在当前选择的行后插入一行或多行文本,如果有两个地址,那将在选定的每一行之后添加文本,如没有地址,则加入到所有行后
    例:[address[address]] a
      text
      text
      …….
      text
    除最后一行外,所添加的文本每一行都必须以反斜杠结尾。sed总是会输出所添加的文本,而不论命令行中是否使用-n 甚至在删除被添加了文本的那一行后。被增加的文本仍会输出     i    插入指令:与append相同,只是将文本添加到选定行之前     c    修改指令:与append类似,不同的是他将选定改为新文本     p    打印指令:将选中行写入标准输出,写入立即发生,不会反映后续指令执行结果     w file  写指令:与print类似,它将输出写入到指定文件中     r file    读指令:读出指定文件的内容并添加到选定行之后     q    退出指令:使sed立即结束     s    sed中的替换指令与vim中的类似
        [address[address]]s/pattern/replacement-string/[g][p][w file]
        可以在replacement-string中使用&,代表当前匹配的字符串   1.4.3 控制结构
    !    使sed后面与其同一行的指令作用于没有被该命令选中的每一行
        例:3!d表示删除除第3行外所有行
          $!p 显示除最后一行外的所有行     {}    指令组:一旦使用一对花括号将一组指令括起来,则这组指令将作用于它前要的地址选定行,使用; 可将多条命令分开     分支指令 sed 的info中指出,Sed并不宜使用分支,建议用awk或perl
    :label  标识sed程序中一个位置,标号label作为跳转目标     b[label]  无条件转移到label处:如没有指定分支目标,则跳过当前行中剩下的指令并从输入中读取下一行     t[label]  如果最近从输入中读取的行使得substitnte指令匹配成功,则到label处, 如没有指定分支目标,则跳过当前行中剩下的指令并从输入中读取下一行   1.4.4 Pattern区与Hold区
    sed中有两个缓冲区,所有的命令都是工作在pattern区的,pattern区中保存着sed刚刚从输入中读取的行,作为临时缓冲区,Hold区可以在操作Pattern区中数据时来暂存数据,在将数据放入Hold之前,它是空的
    关于Pattern区与Hold区之间的数据传送
    g  将Hold区内容复制到Pattern区中,Pattern区中原来的内容丢失
    G  将一个换行符与Hold区中的内容追加到Pattern区中内容之后
    h  将Pattern中内容复制到Hold中,Hold中原来的内容将丢失
    H  将一个换行符与Pattern区中的内容追加到Hold区中内容之后
    x  将Pattern 区与Hold区做交换 1.5 示例
  例1: [root@redhat test]# cat new
    Line one.
    The second line.
    The third.
    This is line four.
    Five.
    This is the sixth sentence.
    This is line seven.
    Eighth and last.
    [root@redhat test]# sed '/line/ p' new
    Line one.
    The second line.
    The second line.
    The third.
    This is line four.
    This is line four.
    Five.
    This is the sixth sentence.
    This is line seven.
    This is line seven.
    Eighth and last.
    [root@redhat test]# sed -n '/line/ p' new
    The second line.
    This is line four.
    This is line seven.
    除非特别指出,否则sed将在标准输出上输出所有的行,无论它是否被选定。当在命令行中使用-n选项时,sed仅仅在标准输出上输出特] ]>

bash中的字符串处理

bash中的字符串处理
  1 得到字符串长度
    [root@redhat test]# s=abcdef
    [root@redhat test]# expr length $s
    6
    [root@redhat test]# echo ${#s}
    6
    [root@redhat test]# expr "$s" : ".*"
    6

  2 查找子串
    [root@redhat test]# expr index $s a
    1
    [root@redhat test]# expr index $s b
    2
    [root@redhat test]# expr index $s c
    3
    [root@redhat test]# expr index $s d
    4
    [root@redhat test]# expr index $s e
    5
    [root@redhat test]# expr index $s f
    6
    [root@redhat test]# expr index $s g
    0

  3 得到子字符串
    语法1:expr substr startpos length 第一个字符序号为1
    [root@redhat test]# expr substr $s 1 3
    abc
    [root@redhat test]# expr substr $s 1 11
    abcdef
    [root@redhat test]# expr substr $s 3 4
    cdef
    [root@redhat test]# expr substr $s 3 1
    c
    [root@redhat test]# m=1
    [root@redhat test]# j=2
    [root@redhat test]# expr substr $s $m $j

    语法2:${x:pos:length} 第一个字符的序号为0
    [root@redhat test]# expr ${s:0:1}
    a
    [root@redhat test]# expr ${s:2:2}
    cd
    [root@redhat test]# expr ${s:2:11}
    cdef
    [root@redhat test]# m=1
    [root@redhat test]# j=2
    [root@redhat test]# expr ${s:$m:$j}
    bc

  4 匹配正则表达式
    [root@redhat test]# expr match $s "ab"
    2
    [root@redhat test]# expr match $s "abc"
    3
    [root@redhat test]# expr match $s "bc"
    0

  5 修改字符串掐头去尾
    #  去除最小匹配前缀
    ##  去除最大匹配前缀
    %  去除最小匹配后缀
    %%  去除最大匹配后缀
    [root@redhat test]# x=cccdddcccpicxxyyyxxx
    [root@redhat test]# echo ${x%x*x}
    cccdddcccpicxxyyyx
    [root@redhat test]# echo ${x%%x*x}
    cccdddcccpic
    [root@redhat test]# echo ${x#c?c}
    dddcccpicxxyyyxxx
    [root@redhat test]# echo ${x#c*c}
    cdddcccpicxxyyyxxx
    [root@redhat test]# echo ${x#c*c}
    cdddcccpicxxyyyxxx
    [root@redhat test]# echo ${x##c*c}
    xxyyyxxx
    这里正则用的特殊符号是? * 并非 . *

  6 字符串替换
    [root@redhat test]# x=efefefef
    [root@redhat test]# echo ${x/e/f}
    ffefefef
    [root@redhat test]# echo ${x//e/f}
    ffffffff
    [root@redhat test]# x=efefacacefacefcb
    [root@redhat test]# echo ${x//ef/f}
    ffacacfacfcb
    [root@redhat test]# echo ${x/ef/f}
    fefacacefacefcb
    [root@redhat test]# echo ${x/e??/f}
    ffacacefacefcb
    [root@redhat test]# echo ${x//e??/f}
    ffacacfcfb
    [root@redhat test]# echo ${x/f*/z}
    ez
    这里正则用的特殊符号是? * , 不可以使用 regexp

gawk 模式处理语言 学习笔记

gawk 模式处理语言
特性:
  1 灵活的格式  2 条件执行  3 偱环语句  4 数值变量
  5 字符串变量  6正则表表式  7关系表达式  8 c语言printf
  9 协进程    10 网络数据交换

1.1 语法
  gawk [options][program][file-list]
  gawk [options] -f program-file [file-list]
  gawk可以从指定文件中或标准输入获取输入
  使用getline可以对输入有更多选择
  协进程(coprocess)可以使gawk与另一个程序进行交互或通过网络交换数据

1.2 参数
  参数中的program是用户在命令行中所包含有gawk的程序
  program-file是存放gawk程序的文件
  在命令行上使用gawk要加单引号
  file-list是输入文件如不指定,则由标准输入,getline或协进程获取

1.3 选项
  –field-seperator fs      -F fs        将fs作为输入字段分隔符的值
  –file program-file      -f program-file    存放gawk程序
  –help          -W help      总结如何使用gawk
  –lint            -W lint      对不正确或不利于移植的结构发出警告
  –posix          -W posix      运行POSIX兼容版的gawk
  –traditional        -W traditional    忽略gawk中的新特性与awk兼容
  –assign var=value      -v var=value    给变量赋值

1.4 注意
  很多linux将/bin/awk链接到了/bin/gawk上

1.5 语言基础
  gawk 程序由一行或多行文本构成,其中包含一个模式和动作
  pattern {action}
  模式(pattern)用来从输入中选取文本行,对于模式选中的每行文本,都执行相应的对作
  如程序中不包含模式,gawk将选取所有行,如果不包含动作gawk将把选中的行复制到标准输出

  1.5.1 模式
    用斜杠把正则表达式包装起来,就可以作为模式使用
    ~操作符测试是否匹配正则表达式 !~测试不匹配
    用||或 &&来组合任何模式
    关系操作符包括:<,>,<=,>=,=,!=
    BEGIN与END是两个独特的模式分别是在gawk开始处理之前与处理之完毕之后的命令
    ,逗号,用逗号隔开的两个模式将选取匹配第一个模式行到匹配第二个模式的下一行

  1.5.2 动作
    gawk如果匹配某个模式,它将执行指定动作,如果没有指定动作,那将执行默认(可用{print}表示)如在print后带上参数,gawk将只显示指定参数。可将print输出发送到文件>追加>>或者通过管道发纷呈另一个程序|
    协进程|& 是一个双向的管道,可以与运行在后台的程序交换数据
    逗号用于print命令中把各项区分开
    通过分号可将多个动作隔开,可以在一行上包含多个动作。

  1.5.3 注释
    #是gawk的注释符号

  1.5.4 变量
    gawk的模式部分与动作部分中均可以使用用户变量与程序变量
    $0      当前记录
    $1-$n    当前记录中的字段
    FILENAME  当前输入文件名
    FS      输入字段的分隔符
    NF      当前记录的字段数目
    NR      当前记录的编号
    OFS      输出字段分隔符
    ORS      输出记录分隔符
    RS      输入记录分隔符

  1.5.5 函数
    length(str)      返回str中的字符数,如没参数,返回当前记录字符数
    int(num)        返回 num的整数部分
    index(str1,str2)    返回str2在str1中出现的位置,如不存在返回 0
    split(str,arr,del)    以del做分隔符,将str中的元素放到数组 arr中,返回个数
    sprintf(fmt,args)    根据fmt格式化args并返回格式化后的字符串
    substr(str,pos,len)    返回str 中从pos开始长度为len个字符的字符串
    tolower(str)      返回str副本,并转成小写字母
    toupper(str)      返回str副本,并转成大写字母

  1.5.6 算术操作符
    *,/,%,+,-,=,++,–,+=,-=,*=,/=,%=

  1.5.7 关联数组
    语法:array[string]=value
    可以将特殊的for结构用于关联数组
    语法如下:
    for (elem in array) action
    在for 遍历数组元素时,elem表示数组中每个元素的值,array为数组名称action为gawk对数组中每个元素所采取的动作,可以在action中使用elem变量。详细见1.6节

  1.5.8 printf
    可以使用printf来代替print控制gawk的输出,gawk版的printf类似于 C
    语法:printf "control-string",arg1,arg2,…,argn
      control-string决定了printf如何格式化arg
      可以在contral-string中使用/n来表示换行符,/t表示TAB
      control-string包含了转换规格,每个参数对应一个转换规格语法
      %[-][x[.y]]conv
      其中-使printf将参数左对齐,x表示最小字段宽度
      .y表示数字中小数点右边的位数,conv表示数值转换的类型
      conv        转换类型
      d      十进制
      e      指数表示
      f      浮点数字
      g      使用f或e中较短的那个
      o      无符号八进制
      s      字符串
   &nb

sp;  x      无符号十六进制

  1.5.9 控制结构
    1 if…else
      语法:(else可选)
        if (condition)
          {commands}
        [else
          {commands}]
      例1:if ($5<=5000) print $0
      例2:cat ifl
        BEGIN {
            nam="sam"
            if (nam=="max")
              print "name is max"
            else
              print "name is not max,it is",nam
            }
          gawk -f ifl

    2 while
      语法:while (condition)
          {commands}
      例:cat wh
        BEGIN {
            n=1
            while (n<=5)
              {
                print n"^2",2**n
                n++
              }
            }
        gawk -f wh

    3 for
      语法:for (init;condition;increment)
          {commands}
      例:cat forl
        BEGIN {
            for (n=1;n<=5;n++)
              print n"^2",2**n
            }
        gawk -f forl

      关联数组的for结构
      语法:
        for (var in array)
          {commands}
      例:END {for (name in manf) print name,manf[name]}
      对于关联数组的for 见1.6

    4 break
      结束for或 while最内层循环

    5 continue
      将for 或 while转移到末尾,并断续执行下一次迭代

1.6 示例
  建立一个示例文件 文件包括制造商,型号,生产年代,千里里程数及价格
  cat cars
  plym  fury      1970  73  2500
  chevy  malibu    1990  60  3000
  ford    mustang    1965  45  10000
  volvo  s80      1998  102  9850
  ford    thundbd    2003  15  10500
  chevy  malibu    2000  50  3500
  bmw  325i      1985  115  450
  honda  accord    2001  30  6000
  ford    taurus    2004  10  17000
  toyota  rav4      2002  180  750
  chevy  impata    1985  85  1550
  ford    explor    2003  25  9500
  

例1:
[root@redhat Testsh]# awk '{print}' cars
plym fury 1970 73 2500
chevy malibu 1990 60 3000
ford mustang 1965 45 10000
volvo s80 1998 102 9850
ford thundbd 2003 15 10500
chevy malibu 2000 50 3500
bmw 325i 1985 115 450
honda accord 2001 30 6000
ford taurus 2004 10 17000
toyota rav4 2002 180 750
chevy impata 1985 85 1550
ford explor 2003 25 9500
这是一个缺失模式,因为没有模式,gawk把输入中所有行复制到了输出

例2:
[root@redhat Testsh]# awk '/chevy/' cars
chevy malibu 1990 60 3000
chevy malibu 2000 50 3500
chevy impata 1985 85 1550
缺失模式,只有一个模式,但没有明确动作。斜杠指出chevy是一个正则表达式。在这种情况中将执行默认动作print.将输入中包含chevy的文本行复制到输出
注意:单引号可以阻止某此问题的发生(比如命令行由bash扩展了,导制传递给awk的参数出错)

例3:
[root@redhat Testsh]# awk '{print $3,$1}' cars
1970 plym
1990 chevy
1965 ford
1998 volvo
2003 ford
2000 chevy
1985 bmw
2001 honda
2004 ford
2002 toyota
1985 chevy
2003 ford
显示第三个字段与第一个字段

例4:
[root@redhat Testsh]# gawk '/chevy/ {print $3,$1}' cars
1990 chevy
2000 chevy
1985 chevy
显示包含chevy行的第三个字段与第一个字段

例5:
[root@redhat Testsh]# awk '/h/' cars
chevy malibu 1990 60 3000
ford thundbd 2003 15 10500
chevy malibu 2000 50 3500
honda accord 2001 30 6000
chevy impata 1985 85 1550
显示包含字母h的行

例6:
[root@redhat Testsh]# gawk '$1~/h/' cars
chevy malibu 1990 60 3000
chevy malibu 2000 50 3500
honda accord 2001 30 6000
chevy impata 1985 85 1550
显示第一个字段包含h的行

例7:
[root@redhat Testsh]# gawk '$1~/^h/' cars
honda accord 2001 30 6000
显示第一个字段第一个字母是h的行

例8:
[root@redhat Testsh]# gawk '$2~/^[tm]/ {print $3,$2,"$"$5}' cars
1990 malibu $3000
1965 mustang $10000
2003 thundbd $10500
2000 malibu $3500
2004 taurus $17000
选中第2个字段以t或m开头的行,并显示第3个字段和第2个字段, 1个美元符号以及第5个字段

例9:
[root@redhat Testsh]# gawk '$3~/5$/ {print $3,$1,"$"$5}' cars
1965 ford $10000
1985 bmw $450
1985 chevy $1550
$使用的三个作用,5$是对行尾或字段尾进行匹配,$加数字的方式表示某字段,"$"代表它自己

例10:
[root@redhat Testsh]# gawk '$3==1985' cars
bmw 325i 1985 115 450
chevy impata 1985 85 1550
显示第三个字段为1985的行

例11:
[root@redhat Testsh]# awk '$5<=3000' cars
plym fury 1970 73 2500
chevy malibu 1990 60 3000
bmw 325i 1985 115 450
toyota rav4 2002 180 750
chevy impata 1985 85 1550
列出字段5小于等于3000的行

例12:
[root@redhat Testsh]# awk '$5>2000 && $5<9000' cars
plym fury 1970 73 2500
chevy malibu 1990 60 3000
chevy malibu 2000 50 3500
honda accord 2001 30 6000
列出$5数值是2000与9000之间的行

[root@redhat Testsh]# awk '$5>"2000" && $5<"9000"' cars
plym fury 1970 73 2500
chevy malibu 1990 60 3000
chevy malibu 2000 50 3500
bmw 325i 1985 115 450
honda accord 2001 30 6000
toyota rav4 2002 180 750
列出$5数值是2000与9000之间的行,但由于2000与9000加了双引号,即进行正文比较(使用ASCII比较)

例13:
[root@redhat Testsh]# awk '/volvo/,/bmw/' cars
volvo s80 1998 102 9850
ford thundbd 2003 15 10500
chevy malibu 2000 50 3500
bmw 325i 1985 115 450
选中由逗号之前的模式指定的行致逗号之后模式匹配的行,如果没有匹配逗号之后的文本行,则会将选取到输入末尾

[root@redhat Testsh]# cat cars
plym fury 1970 73 2500
chevy malibu 1990 60 3000
ford mustang 1965 45 10000
volvo s80 1998 102 9850
ford thundbd 2003 15 10500
chevy malibu 2000 50 3500
bmw 325i 1985 115 450
honda accord 2001 30 6000
ford taurus 2004 10 17000
toyota rav4 2002 180 750
chevy impata 1985 85 1550
ford explor 2003 25 9500

[root@redhat Testsh]# awk '/chevy/,/ford/' cars
chevy malibu 1990 60 3000
ford mustang 1965 45 10000
chevy malibu 2000 50 3500
bmw 325i 1985 115 450
honda accord 2001 30 6000
ford taurus 2004 10 17000
chevy impata 1985 85 1550
ford explor 2003 25 9500
上边例子在找到第一组文本行之后,它将再次进行处理,查找匹配逗号异军突起前的文本行。awk查找落入chevy和ford之间的所有的三组文本行。尽管输入的每5行包含ford,但gawk并没有选择它,因为此时它正在处理第5行,正在搜索chevy

例14:
[root@redhat Testsh]# cat awk_t
BEGIN {print "make model year miles pricen"}
{print}

[root@redhat Testsh]# awk -f awk_t cars
make model year miles price

plym fury 1970 73 2500
chevy malibu 1990 60 3000
ford mustang 1965 45 10000
volvo s80 1998 102 9850
ford thundbd 2003 15 10500
chevy malibu 2000 50 3500
bmw 325i 1985 115 450
honda accord 2001 30 6000
ford taurus 2004 10 17000
toyota rav4 2002 180 750
chevy impata 1985 85 1550
ford explor 2003 25 9500
一个简单的用-f 参数指定 awk程序文件的例子

例15: (length的使用)
[root@redhat Testsh]# awk '{print length"t",$0}' cars|sort -n
21 bmw 325i 1985 115 450
22 plym fury 1970 73 2500
23 volvo s80 1998 102 9850
24 ford explor 2003 25 9500
24 toyota rav4 2002 180 750
25 chevy impata 1985 85 1550
25 chevy malibu 1990 60 3000
25 chevy malibu 2000 50 3500
25 ford taurus 2004 10 17000
25 honda accord 2001 30 6000
26 ford mustang 1965 45 10000
26 ford thundbd 2003 15 10500
此例使用了length函数来显示每行的字符个数,t是一个TAB,用来对齐
sort -n 对数字进行排序

例16:(NR的意义:行编号)
[root@redhat Testsh]# awk 'length>24 {print NR"t",$0}' cars
2 chevy malibu 1990 60 3000
3 ford mustang 1965 45 10000
5 ford thundbd 2003 15 10500
6 chevy malibu 2000 50 3500
8 honda accord 2001 30 6000
9 ford taurus 2004 10 17000
11 chevy impata 1985 85 1550
显示出字符个数大于24的行,并显示行号

例17:
[root@redhat Testsh]# awk 'NR==2,NR==4' cars
chevy malibu 1990 60 3000
ford mustang 1965 45 10000
volvo s80 1998 102 9850
显示从第二行到第四行
例18: (END的使用)
[root@redhat Testsh]# awk '{print}END{print "—END—"}' cars
plym fury 1970 73 2500
chevy malibu 1990 60 3000
ford mustang 1965 45 10000
volvo s80 1998 102 9850
ford thundbd 2003 15 10500
chevy malibu 2000 50 3500
bmw 325i 1985 115 450
honda accord 2001 30 6000
ford taurus 2004 10 17000
toyota rav4 2002 180 750
chevy impata 1985 85 1550
ford explor 2003 25 9500
—END—
在处理完输入之后才执行END指定的语句

例19:
[root@redhat Testsh]# cat awk_t1
{
if ($1~/ply/) $1="plyssj"
if ($1~/chev/) $1="chevssj"
print
}
[root@redhat Testsh]# awk -f awk_t1 cars
plyssj fury 1970 73 2500
chevssj malibu 1990 60 3000
ford mustang 1965 45 10000
volvo s80 1998 102 9850
ford thundbd 2003 15 10500
chevssj malibu 2000 50 3500
bmw 325i 1985 115 450
honda accord 2001 30 6000
ford taurus 2004 10 17000
toyota rav4 2002 180 750
chevssj impata 1985 85 1550
ford explor 2003 25 9500
给$1赋值的例子

例20:(建立独立的awk脚本)
[root@redhat Testsh]# cat if.ak
#!/bin/awk -f
{
if ($1~/ply/) $1="plyssj"
if ($1~/chev/) $1="chevssj"
print
}
[root@redhat Testsh]# if.ak cars
plyssj fury 1970 73 2500
chevssj malibu 1990 60 3000
ford mustang 1965 45 10000
volvo s80 1998 102 9850
ford thundbd 2003 15 10500
chevssj malibu 2000 50 3500
bmw 325i 1985 115 450
honda accord 2001 30 6000
ford taurus 2004 10 17000
toyota rav4 2002 180 750
chevssj impata 1985 85 1550
ford explor 2003 25 9500

例21:(printf的使用)
[root@redhat Testsh]# cat if1.ak
#!/bin/awk -f
BEGIN{
print " Miles"
print "Make Model year (000) price"
print "——————————————-"}
{if ($1~/ply/) $1="plyssj"
if ($1~/chev/) $1="chevssj"
printf "%-10s %-8s %-5d %-5d $ %8.2fn",$1,$2,$3,$4,$5
}
[root@redhat Testsh]# if1.ak cars
Miles
Make Model year (000) price
——————————————-
plyssj fury 1970 73 $ 2500.00
chevssj malibu 1990 60 $ 3000.00
ford mustang 1965 45 $ 10000.00
volvo s80 1998 102 $ 9850.00
ford thundbd 2003 15 $ 10500.00
chevssj malibu 2000 50 $ 3500.00
bmw 325i 1985 115 $ 450.00
honda accord 2001 30 $ 6000.00
ford taurus 2004 10 $ 17000.00
toyota rav4 2002 180 $ 750.00
chevssj impata 1985 85 $ 1550.00
ford explor 2003 25 $ 9500.00
例22:(重定向输出)
[root@redhat Testsh]# cat awk_out
/chevy/ {print > "chevfile"}
/ford/ {print > "fordfile"}
[root@redhat Testsh]# awk -f awk_out cars
[root@redhat Testsh]# cat chevfile;echo "";cat fordfile
chevy malibu 1990 60 3000
chevy malibu 2000 50 3500
chevy impata 1985 85 1550

ford mustang 1965 45 10000
ford thundbd 2003 15 10500
ford taurus 2004 10 17000
ford explor 2003 25 9500

例23:(使用FS )
[root@redhat Testsh]# cat find_uid
#!/bin/awk -f
BEGIN{FS=":"
saveit=0}
$3>saveit {saveit=$3}
END{print "Max UID is " saveit }
[root@redhat Testsh]# find_uid /etc/passwd
Max UID is 65534
[root@redhat Testsh]# awk -F: '{print $3}' /etc/passwd |sort -n|tail -5
556
557
558
559
65534

例24:
[root@redhat Testsh]# cat manuf
#!/bin/bash
gawk '{manuf[$1]++} END {for (name in manuf) print name,manuf[name]}' cars |sort
[root@redhat Testsh]# bash ./manuf
bmw 1
chevy 3
ford 4
honda 1
plym 1
toyota 1
volvo 1
关联数组使用cars文件中每条记录的第1个字段的内容作为索引。这个数组由元素manuf[plym],manuf[chevy]等组成。每个元素在创建时都被初始化为0

例25:
[root@redhat Testsh]# cat word_usage
#!/bin/bash
tr -cs '[a-zA-Z]' '[n*]' < $1|gawk '{count[$1]++}END {for (item in count) printf "%-15s %-4d n", item,count[item]}'|sort +1nr +0f -1
[root@redhat Testsh]# bash ./word_usage text.txt |head -5
the 64
is 35
of 28
a 21
and 21
……
显示文件中单词的使用情况列表

例26:
[root@redhat Testsh]# cat report
#!/bin/bash
if [ $# == 0 ] ;then
echo "you must supply a filename"
exit 1
fi
(date;cat $1)|awk '
NR==1 {print $6,$2,$3,$4}
NR>1 {printf "%-10s%-15sn", $5,$1}'
[root@redhat Testsh]# bash ./report cars
2009 7月 30 10:55:07
2500 plym
3000 chevy
10000 ford
9850 volvo
10500 ford
3500 chevy
450 bmw
6000 honda
17000 ford
750 toyota
1550 chevy
9500 ford
一个把日期加入报告中的办法
getline与协进程先不讨论了,一般用不到

练习:
1 编写一个gawk程序对文件中的每行编号,然后将它的输出发送到标准输出
[root@redhat root]# cat g4
{print NR,$0
}
[root@redhat root]# cat tt
aaaa 1111
bbbb 2222
cccc 3333
dddd 4444
[root@redhat root]# gawk -f g4 <tt
1 aaaa 1111
2 bbbb 2222
3 cccc 3333
4 dddd 4444

2 编写一个gawk程序,显示第1个字段中的字符数目,后面跟着第1个字段,然后将输出发送到标准输出
[root@redhat root]# cat g5
{print length($1),$1
}
[root@redhat root]# cat tt
aaaa 1111
bbbb 2222
cccc 3333
dddd 4444
[root@redhat root]# gawk -f g5 <tt
4 aaaa
4 bbbb
4 cccc
4 dddd

3 编写一个gawk程序,使用cars文件,显示所有价格高于5000美元的汽车,然后将其输出发送到标准输出
[root@redhat root]# awk -f g5 < /root/Testsh/cars
ford mustang 1965 45 10000
volvo s80 1998 102 9850
ford thundbd 2003 15 10500
honda accord 2001 30 6000
ford taurus 2004 10 17000
ford explor 2003 25 9500

4 使用gawk来判断/etc/termcap中有多少行包含了字符串vt100.使用grep验证一下自己的程序
[root@redhat root]# cat g5
{if ($0~/vt100/)
num+=1
}
END{print num}
[root@redhat root]# time awk -f g5 /etc/termcap
174

real 0m0.142s
user 0m0.140s
sys 0m0.010s

验证:

[root@redhat root]# time grep -c vt100 < /etc/termcap
174

real 0m0.317s
user 0m0.310s
sys 0m0.010s

还是awk比较快

正则表达式 学习笔记

正则表达式
前言:ed vim emacs grep gawk sed等工具使用的正则表达式,这些表达式与shell的模糊文件引用中使用的正则表达式是不同的

A1 字符
   字符是除换行之外的其他任意字字符。正则表达式中的大多数字符代表它们自身,而那些不代表自身的字符称为特殊字符。如果需要特殊字符代表自身,那么就需要将这些字符转义。

A2 定界符
  正则表达式使用 / 作为定界符,vim中允许使用其它定界符,而grep不使用任何定界符。在一些含义不模糊的情况下,第2个定界符不是必要的。例如,当第2个定界符后面要紧跟RETURN时,就可以省略第2 个定界符

A3 简单字符串
最基本的正则表达式是只包含非特殊字符和定界符的简单字符串。简单字符串只与它自身匹配
正则表达式  匹配字符串  示例
/ring/  ring  
/Thursday/  Thursday  
/or not/  or not  

A4 特殊字符
  正则表达式中使用特殊字符可以使得正则表达式匹配多个字符串

  A4.1 句点
  /.alk/ 句点匹配任意单个字符,该字符不能为空

  A4.2 方括号
  /[bB]ill/  与bill和Bill匹配
  /t[aeiou].k/  与t后跟元音字母匹配
  /# [6-9]/  与#后跟空格再跟6到9之间的数字的字符串匹配
  /[^a-zA-Z]/ 与26个字母之外的任意字符匹配

  A4.3 星号
  * 跟随在代表某个字符的正则表达式之后,表示与该正则表达式所匹配的 0个或多个匹配,跟在句点后的星号可以匹配任意字符串,字符定义类后跟星号可以匹配包含该类定义的成员字符的任意字符串
  /ab*c/  a后跟0个或多个b后再跟c的字符串匹配
  /ab.*c/ 与ab后跟0个或多个字符再跟c的字符串匹配
  /t.*ing/ 与t后跟0个或多个字任再跟ing的字符串匹配
  /[a-zA-Z]*/ 与由字母和空格组成的字符串匹配
  /(.*)/ 与圆括号括起来的最长字符串匹配
  /([^)]*)/ 与圆括号括起来的最短字符串匹配
  A4.4   脱字符与美元符号
    以脱字符开始的正则表达式只能匹配位于行首的字符串,以美元符号结尾的正则表    达式只能匹配行末尾的字符串
    /^T/  与位于行首的T匹配
    /^+[0-9]/ 与位于行且由加号后跟一个数字组成的字符串匹配
    /:$/ 与位于行尾的:匹配

  A4.5 转义特殊字符
    在特殊字符之前使用反斜杠可以转义除数字和圆括号外的特殊字符。
    /end./  与end后跟一个句点的字符串匹配
    /\/  与单独一个反斜杠匹配
    /*/ 与单独一个星号匹配
    /[5]/  与 [5]匹配
    /and/or/  与and/or匹配

A5 规则
  A5.1 最长匹配
    正则表达式总是与尽可能长的字符串匹配,从行的开始尽可能地向前匹配
    例如:This (rug) is not what it once was (a long time ago),is it?
    表达式/Th.*is/将匹配
    This (rug) is not what it once was (a long time ago),is
    表达式/(.*)/将匹配
    (rug) is not what it once was (a long time ago)
    表达式/([^)]*)/将匹配
    (rug)
  
  A5.2 空正则表达式
    对于某此工具例如vim 和less,但对于grep不适用,空正则表达式代表上次使用的表达式。例如在vim 中使用下面的替换命令
    :/s/mike/robert
    如要再次使用该替换可以使用下面的
    :s//robert/
    或者
    先查找mike串,再进行替换
    /mike/
    :s//robert/
    其中的空正则表达式(//)代表上次使用的正则表达式(/mike/)

A6 括号表达式
  使用转义圆括号可以将下则表达式括起来。但并不会改变匹配效果例如下例
  /a(b*)c/与/ab*c/是一样的

A7 替换字符串
  A7.1 &符号
    在替换字符串中&代表搜索字符串所匹配的字符串的值,例
    在文件 123 123 456 567使用:s/[0-9][0-9]*/(&)
    结果是(123) (123) (456) (567)

  A7.2 转义数字
    last-name, first-name initial
    转成first-name initial last-name

    :1,$s/([^,]*), (.*)/2 1/

A8 扩展的正则表达式
  工具egrep,带-E的工具grep,和gawk
  我没找到用的地方,先不细写了,用到了再加上
  redhat vi,grep都用不了

A9 小结
正则表达式中的特殊字符
.  与单个字符匹配
*  与*前边一个字符的0个或多个匹配
^  与行的开始匹配,在[]中表示不包括在类中
$  与行的末尾匹配
  用来转义的
<  与字的开始匹配
>  与字的末尾匹配

扩展正则

替换字符串
&  代表匹配的字符串
n  转义n代表第n个被括号正则表达式所匹配的字符串