s
Android adb shell / ADB: Android debug bridge.
Android手机实际是基于Linux系统的。
在你的android手机的设置中,Settings->Applications->Development->USB debugging勾选上,就可以允许PC通过adb shell命令远程登录你手机的linux系统
【安卓手机通用】android adb shell 命令大全
http://jingyan.baidu.com/article/8cdccae9955c4c315413cda8.html
adb shell 是什么,如何进入?
http://blog.csdn.net/xiebaochun/article/details/29558417
ADB 调试桥
http://baike.baidu.com/view/46000.htm#3
概述
adb的全称为Android Debug Bridge,就是起到调试桥的作用。通过adb我们可以在Eclipse中方便通过DDMS来调试Android程序,说白了就是debug工具。adb的工作方式比较特殊,采用监听Socket TCP 5554等端口的方式让IDE和Qemu通讯,默认情况下adb会daemon相关的网络端口,所以当我们运行Eclipse时adb进程就会自动运行。
adb是android sdk里的一个工具, 用这个工具可以直接操作管理android模拟器或者真实的andriod设备(如G1手机). 它的主要功能有:
* 运行设备的shell(命令行)
* 管理模拟器或设备的端口映射
* 计算机和设备之间上传/下载文件
* 将本地apk软件安装至模拟器或android设备
ADB是一个 客户端-服务器端 程序, 其中客户端是你用来操作的电脑, 服务器端是android设备.
常用命令
[1] 1. 查看设备 *adbdevices
这个命令是查看当前连接的设备, 连接到计算机的android设备或者模拟器将会列出显示
2. 安装软件
*adbinstall <apk文件路径>
这个命令将指定的apk文件安装到设备上
3. 卸载软件
*adbuninstall <软件名>
*adbuninstall -k <软件名>
如果加 -k 参数,为卸载软件但是保留配置和缓存文件.
4. 登录设备shell
*adbshell
*adbshell <command命令>
这个命令将登录设备的shell.
后面加<command命令>将是直接运行设备命令, 相当于执行远程命令
5. 从电脑上发送文件到设备
*adbpush <本地路径> <远程路径>
用push命令可以把本机电脑上的文件或者文件夹复制到设备(手机)
6. 从设备上下载文件到电脑
*adbpull <远程路径> <本地路径>
用pull命令可以把设备(手机)上的文件或者文件夹复制到本机电脑
7. 显示帮助信息
*adbhelp
这个命令将显示帮助信息
删除Android系统Rom自带的软件
Android系统没有卸载Rom自带软件的功能.可能有些同学很想删除废了武功的Youtube,想删除墙那边的Twitter.
加上Android的快捷方式没法修改没法自己排序没法分页.
安装的程序太多就会发现原来找到自己想要的东西很难.
综上所述,我觉得告知各位菜鸟同学如何删除自带的程序是很有必要的一件事情.
1.确定手机root了,取得了root权限才能删除系统文件呀.
2.下载Android_db.rar,解压到%windir/%System32下.
3.手机连接数据线,在电脑上打开cmd,然后输入命令
adb remount
adb shell
su
执行完成之后,你会看到:
* daemon not running. starting it now *
* daemon started successfully *
4.接着就是Linux命令行模式了,输入
cd system/app
你会发现没啥变化,然后输入ls回车.
这时候列表显示了system/app里面的所有文件,也就是Rom集成的一些软件了.
5.开始删除吧.比如删除Youtube,他的文件名是Youtube.odex和Youtube.apk
我们要删除这2个文件,敲入以下命令:
adb shell rm -f system/app/Youtube.odex
adb shell rm -f system/app/Youtube.apk
基本上shell分两大类:
一:图形界面shell(Graphical User Interface shell 即 GUI shell)
Windows Explorer
X windows manger (BlackBox和FluxBox)和CDE、GNOME、KD、 XFCE等
二:命令行式 shell(Command Line Interface shell ,即CLI shell)
『Unix/linux 系统』bash / sh / ksh / csh / tcsh
Bourne shell (包括 sh, ksh, and bash)
Bourne shell ( sh)
Korn shell ( ksh)
Bourne Again shell ( bash)
POSIX shell ( sh)
C shell (包括 csh and tcsh)
C shell ( csh)
TENEX/TOPS C shell ( tcsh)
Bourne Shell
各主要操作系统下缺省的shell:
AIX 下是Korn Shell.
Solaris 和FreeBSD 缺省的是Bourne shell.
HP-UX 缺省的是POSIX shell.
Linux 是Bourne Again shell.
『MS-DOS 系统』COMMAND.COM
『Windows NT 系统』 cmd.exe
『支援 .NET Framework 技术的 Windows NT 系统』Windows PowerShell
Shell也是一个VB函数,它的作用是运行程序,语法是Shell(命令字符串[,窗口类型])
Redhat Linux Shell
http://robertmei.ycool.com/post.2944742.html
用命令“echo $SHELL”可以查看当前shell是什么。
/bin/bash ------------------- Bash Shell
/bin/csh ------------------- C Shell
/bin/ksh ------------------- Kron Shell
/sbin/sh ------------------- Bourne Shell
http://dl.iteye.com/topics/download/3a17246e-f4dd-3dbb-89c5-9c4383f4e60e
basic_shell_programming_1_.pdf
http://dl.iteye.com/topics/download/9e23a3ed-9b41-3648-a9e4-15a1243067e7
bash编程学习笔记_1_.rar
Redhat Enterprise 5.3 x64 增加彩色vim编辑器(未完, 基本对照)
download vim.tar
http://dl.iteye.com/topics/download/ddbb7a55-06ee-35cd-a5d3-066aefb5d93a
[root@b2cpreweb2 ~]# tar -xvf /usr/bin/vim.tar
[root@b2cpreweb2 ~]# ls -l /usr/bin/vim*
-rwxrwxrwx 1 root root 2871552 Nov 17 15:29 /usr/bin/vim
lrwxrwxrwx 1 root root 5 Nov 17 15:37 /usr/bin/vimdiff -> ./vim
-rw-r--r-- 1 root root 2877440 Nov 17 15:37 /usr/bin/vim.tar
-rwxrwxrwx 1 root root 1600 Nov 17 15:29 /usr/bin/vimtutor
[root@b2cpreweb2 ~]# rm /usr/bin/vimdiff
[root@b2cpreweb2 ~]# ln -s /usr/bin/vim /usr/bin/vimdiff
增加bash shell history的时间戳
[root@nginx1 ~]# vim .bashrc
1 # .bashrc
2
3 # User specific aliases and functions
4
5 alias rm='rm -i'
6 alias cp='cp -i'
7 alias mv='mv -i'
8
9 # Source global definitions
10 if [ -f /etc/bashrc ]; then
11 . /etc/bashrc
12 fi
13
14 export HISTTIMEFORMAT="%F %T "
http://topic.csdn.net/u/20080513/08/dfe00716-384e-4810-91b3-513c3fe78f3f.html
按Esc + :wq 保存退出
".bashrc" E514: write error (file system full?)
".bashrc"
".bashrc" E514: write error (file system full?)
Press ENTER or type command to continue
按Esc + :q! 保存退出,检查磁盘空间
[root@b2cpreweb1 ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/VolGroup00-LogVol01
18G 18G 0 100% /
/dev/sda1 99M 13M 82M 13% /boot
tmpfs 2.0G 0 2.0G 0% /dev/shm
192.168.157.111:/opt/SNWCS/
18G 18G 0 100% /opt/SNWCS
Redhat Gnome Terminal 快捷键
http://huangchao200701.iteye.com/blog/263002
常用
win+n切换背景颜色风格
alt+tab=不用说了。
win+tab若开3D效果了切换
ctrl+alt+backspace=相当于强制注销
ctrl+alt+del=调出关机菜单
ctrl+alt+l=锁定桌面
ctrl+alt+d=最小化gnome所有窗口
ctrl+alt+f2=linux终端用户(alt + f7返回xwindows,alt+ <- 或-> 进行终端切换)
ctrl+alt+ <- 或-> =切换桌面
终端快捷键
tab=补全
ctrl+a=开始位置
ctrl+e=最后位置
ctrl+k=删除此处至末尾所有内容
ctrl+u=删除此处至开始所有内容
ctrl+d=删除当前字母
ctrl+w=删除此处到左边的单词
ctrl+y=粘贴由ctrl+u,ctrl+d,ctrl+w删除的单词
ctrl+r=正在测试,还没弄明白,呵呵。
ctrl+l=相当于clear
ctrl+b=向回移动
ctrl+f=向前移动
ctrl+p=向上显示缓存命令
ctrl+n=向下显示缓存命令
ctrl+d=关闭终端
shift+上或下=终端上下滚动
shift+pgup或pgdown=终端上下翻页滚动
ctrl+shift+f=全屏(仅限于konsole)
ctrl+shift+n=新终端(terminal 和konsole有所不同)
ctrl+c=终止
以下为网上的快捷键列表
打开主菜单 = Alt + F1
运行 = Alt + F2
显示桌面 = Ctrl + Alt + d
最小化当前窗口 = Alt + F9
最大化当前窗口 = Alt + F10
关闭当前窗口 = Alt + F4
截取全屏 = Print Screen
截取窗口 = Alt + Print Screen
默认特殊快捷键
展示所有窗口程序 = F10
展示当前窗口最上层程序 = F11
展示当前窗口所有程序 = F12
切换窗口 = Alt + Tab
旋转3D桌面 = Ctrl + Alt + 左/右箭头(也可以把鼠标放在标题栏或桌面使用滚轮切换)
旋转3D桌面(活动窗口跟随) = Ctrl + Shift + Alt + 左/右箭头
手动旋转3D桌面 = Ctrl + Alt + 左键单击并拖拽桌面空白处
窗口透明/不透明 = possible with the “transset” utility or Alt + 滚轮
放大一次 = 超级键 + 右击
手动放大 = 超级键 + 滚轮向上
手动缩小 = 超级键 + 滚轮向下
移动窗口 = Alt + 左键单击
移动窗口时贴住边框 = 左键开始拖动后再 Ctrl + Alt
调整窗口大小 = Alt + 中击
Bring up the window below the top window = Alt + middle-click
动态效果减速 = Shift + F10
水纹 = 按住 Ctrl+超级键
雨点 = Shift-F9
桌面展开= Ctrl + Alt + 下箭头,然后按住 Ctrl + Alt 和左/右箭头选择桌面
shell
http://baike.baidu.com/view/849.htm
在计算机科学中,Shell俗称壳(用来区别于核),是指“提供使用者使用界面”的软件(命令解析器)。
它类似于DOS下的command.com。
它接 收用户命令,然后调用相应的应用程序。
同时它又是一种程序设计语言。
作为命令语言,它交互式解释和执行用户输入的命令或者自动地解释和执行预先设定好的一 连串的命令;
作为程序设计语言,它定义了各种变量和参数,并提供了许多在高阶语言中才具有的控制结构,包括循环和分支。
在C++中,Shell是希尔排序 的名称。
Linux shell 编程系列
http://www.ibm.com/developerworks/cn/linux/shell/index.html#firstmajorhead
Shell 介绍 | |
Bash | |
awk | |
sed | |
Vi、Emacs | |
Shell 使用技巧 |
Shell 变量
HISTFILESIZE 与 HISTSIZE 的区别
http://www.linuxeden.com/forum/viewthread.php?tid=159573
两个变量和命令的 history 记录有关.
HISTFILESIZE 定义了在 .bash_history 中保存命令的记录总数.
HISTSIZE 定义了 history 命令输出的记录数.
HISTTIMEFORMAT 则定义了执行命令的时间格式, 典型的配置 是 '<%F %T>: '
改变量生效后, history 的输出将格式化为:
1052 <2007-10-08 10:13:02>: history
其中 <2007-10-08 10:13:02> 是 history 命令的执行时间.
/etc/profile、~/.bash_profile等几个文件的执行过程
http://blog.chinaunix.net/u2/61187/showart_1189840.html
执行顺序为:
/etc/profile -> (~/.bash_profile | ~/.bash_login | ~/.profile) -> ~/.bashrc -> /etc/bashrc -> ~/.bash_logout
开发人员行走Unix的随身四艺
http://weiruan85.iteye.com/blog/333202
VI+文本处理+Bash Shell 编程+Make or AutoMake
附录A:我的VI易忘命令手册
上下左右:
ctrl+u/d 上下半屏,ctrl+f/b,上下一屏
H/G屏幕头/文章末 ,0/$ 行首行末
增删改:
yy/dd 复制/删除 一行,p/P:将yy/dd的内容paste出来
I/A 在行首/末添加, o/O 开新行,d0/d$ 删除到行首,行末
u:undo
查:
? 向前查找, n/N 重复上一次查找
附录B: 文本处理命令小结
awk:处理结构化的文本(每行以固定符号分成若干列),提取打印某些字段,如:
ls -l|awk '{print $1}' --将ls-l结果的第一列打印出来
awk -F":" '{print $1" "$6}' /etc/passwd ,将以:分割的/etc/passwd文件的第1,6列打印出来,中间以空格分开
详见IBM DW中国的AWK实例(共3篇) 或 Bash新手指南中文版第6章。
grep:过滤,大家用得最多的命令,支持正则表达式。参数有: http://www.hudong.com/wiki/grep
-i忽略大小写,-n显示line number,-c 统计在每个文件的出现次数,-l只显示符合的文件的名字。
grep (global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)
sed:流编辑器,主要用于替换,如:
sed -e '1,10s/foo/bar/g' myfile2.txt 将1到10行的文本中的foo 替换成bar,s代表替换,g代表全局替换
支持正则的替换字符串,可以只替换某个范围内的内容。
用法不算简单,详见IBM DW中国的Sed实例(共3篇)或 Bash新手指南中文版第5章。
sort:排序,参数有:
-r逆序, -n 数字比较 , -M 日历比较 Feb,Dec, -f 忽略大小写
同样支持结构化文件,如
sort -t : -k 1,1 /etc/passwd,以: 分割,只按第1列排序
sort -t : -k 1,1 -k2.2,3.4 /etc/passwd ,以:分割,先按第1列排序,再按第2列的第二个字符到第3列的第4个字符排序。
uniq:去除重复行。
除了正常用法外,还有-c统计重复次数,和-u (唯一)和 -d (重复)两个参数,只显示唯一的和重复的行。
wc: 统计。
-l 行,-m 字符,-w 单词
附录C: 我的automake1.9步骤小结
先编写MakeFile.am
运行autoscan,生成configure.scan
修改configure.scan,同时把文件改名为configure.in :
去除AC_CONFIG_HEADER([config.h])那行
加入AM_INIT_AUTOMAKE([1.9 foreign]) (其中1.9是automake的版本号)
加入AC_PROG_LIBTOOL (如果用libtool的话)
检查AC_CONFIG_FILES,如果之前没有先写齐所有MakeFile.am,autoscan就不会帮你加入,需要自己手工补充。
libtoolize (如果用libtool的话)
aclocal
autoconf
automake --add-missing
./configure
make
大家需要编写的文件从Makefile转为了Makefile.am 和configure.in, ACE的Examples是很好的参考。
vi入门
https://www6.software.ibm.com/developerworks/cn/education/linux/l-vi/tutorial/index.html
shell脚本自动重新启动已停止/僵死的Apache的httpd进程
http://community.itbbs.cn/showthread.php?t=12955
http://bash.cyberciti.biz/web-server/restart-apache2-httpd-shell-script/
[PPT,PDF] Bash Shell 编程基础
http://www.openbsdonly.org/download/file.php?id=67
http://bbs.chinaunix.net/viewthread.php?tid=994745
http://wiki.ubuntu.org.cn/Shell编程基础
http://www.linuxsir.org/main/doc/abs/abs3.7cnhtm/index.html
Shell编程基础
出自Ubuntu中文
本文作者:Leal
授权许可:
编辑人员:FireHare, Dbzhang800
<script type="text/javascript"><!-- --></script>
[编辑 ] 基本格式
我们可以使用任意一种文字编辑器,比如nedit、kedit、emacs、vi等来编写shell脚本,它必须以如下行开始(必须放在文件的第一行):
# !/bin/sh ...
符号#!用来告诉系统执行该脚本的程序,本例使用/bin/sh。编辑结束并保存后,如果要执行该脚本,必须先使其可执行:
chmod +x filename
此后在该脚本所在目录下,输入 ./filename 即可执行该脚本。
[编辑 ] 合理使用注释
shell 脚本中以# 开始的行表示注释,直到该行的结束。我们强烈建议你在脚本中进行适当/合理的注释,这样一来,即便你在相当长时间内没有使用该脚本,也能在短时间内就明白它的作用和工作原理。此外,还有一个很重要的原因是,在注释的帮助下,别人可以快速有效的分享你的脚本,并提出自己的意见和改进。
Linux Shell注释符号 >>># 或 !
http://www.lovetech.cn/2007/05/1.html
ubuntu 完美man
1.添加库函数手册
ubuntu默认是没有安装c语言的库函数man手册的,所以你在man perror 和sendto之类的函数时会显示没有相关文档的问题,这个问题让我郁闷了我好久。解决方法:
sudo apt-get install manpages-dev
2.让man显示中文
ubuntu源里面已经包含了中文的man包,所以不用从其他地方down了,直接
sudo apt-get install manpages-zh
但是这样man默认显示的还不是中文,还需要以下两步
a.把中文man包转换成utf8格式的
新建一个脚本文件
gedit t.sh
把下面内容添加进去
#!/bin/bash
cd /usr/share/man/zh_CN/
for k in *
do
cd $k
for i in *.gz
do
j=`echo ${i%.gz}`
gunzip $i
iconv -f gb18030 -t utf8 $j >tmp
mv tmp $j
gzip $j
done
cd ..
done
然后
sudo ./t
b.修改man默认的语言
sudo gedit /etc/manpath.config
把里面的所有的 /usr/share/man 改成 /usr/share/man/zh_CN
保存后退出,然后你再试一下man ls
3.让没有中文帮助的显示英文
做完上面第二部还不够,这时你再man 一下一些c语言函数(不要用printf,socket之类比较有名的函数,这些已经有中文帮助了)的时候就会发现竟然没有帮助,而刚才明明在第一步已经安装了啊。这是因为你上面 把/usr/share/man 改成 /usr/share/man/zh_CN的操作使man只在中文帮助中搜索,如果没有就直接放弃,因此还需要以下操作,才能让man在没有中文帮助的时候自动显示英文的帮助,如果英文的也没有,哪就真的没有了。
sudo gedit /etc/manpath.config
然后搜索你刚才改过的地方,然后在其后面添加同样的一行,只是后面的目录还用原来的 /usr/share/man,比如在修改后的
MANPATH_MAP /bin /usr/share/man/zh_CN
再添加一行
MANPATH_MAP /bin /usr/share/man
参考: http://csf.swfc.edu.cn/phpbb/viewtopic.php?p=6684
再多唠叨一句:man显示的函数只有枯燥的用法,看起来不是很爽,在此推荐一个查c语言函数的网站http://www.cplusplus.com/ ,上面有每个函数的用法以及实例。
巩固shell基础知识
以下这些知识是在编写shell程序的时候要用到的,需要的时候可以来查查,来巩固一下吧
shell中的一些扩展字符
• !! 上个命令的所有字符
• !* 一个命令的所有参数
• !^ 上一条命令的第一个参数
• !$ 上一条命令的最后一个参数
• !:3 上一条命令的第3个参数
• !:0 命令
• !:x x指示 可以是^ $ x-y * x*(第x个起) x-(不包括$) % n 0
• !n history中的第n条命令,-n表示最后倒数的。
• !?xxx 包含xxx的最后一个命令
• !xxx xxx开头的最后一个命令
• ^string1^string2^ 快速替换。重复上一条命令,将 string1 替换为 string2. 与 ``!!:s/string1/string2/''
修饰符 (Modifiers)
可选的 word 指示器之后,可以出现一个或多个下述 modifiers 的序列,每一个都前缀有 `:'。
h 删除文件名组成的尾部,只保留头部(路径)。
t 删除文件名组成中前面的成分,保留尾部(文件)。
r 删除 .xxx 形式中尾部的后缀成分,保留基本名称部分。
e 删除所有内容,保留尾部的后缀。
p 打印新的命令,但是不执行它。
q 引用替换所得的词,使它不再进行替换。
x 引用替换所得的词,类似与 q, 但是会根据 blanks,空白 和新行符分解为词。
s/old/new/
将事件行中出现的第一个 old 替换为 new。 任何分隔符都可以用来代替
/,最后一个分隔符是可选的,如果它是事件行的最后一个字符。 old 和 new 中的分隔符可以用一个反斜杠来引用。如果 &
出现在 new 中,它将替换为 old。 可以用单个反斜杠来引用 &。如果 old 为空,它将设置为最后替换的 old,
或者,如果前面没有发生过历史替换,就是 !?string[?] 搜索中的最后一个 string。
& 重复上一次替换。
g 使得改变被整个事件行所接受。用于与 `:s' 或 `:&' 结合 (例如,`:gs/old/new/')。 如果与 `:s'
结合使用,任何分隔符都可以用来代替 /, 最后一个分隔符是可选的,如
果它是事件行的最后一个字符。
$ mv foo.{jpeg,jpg}
这个命令将把foo.jpeg改名为foo.jpg。
bash脚本的参数
$0:脚本名字。此变量包含地址,可以使用basename $0获得脚本名称。
$1:第一个参数
$2,$3,$4,$5,…一次类推。
$# 传递到脚本的参数个数
$* 以一个单字符串显示所有向脚本传递的参数
$$ 脚本运行的ID号
$! 后台运行的最后一个进程的ID号
$@ 与$#相同,但是使用时加引号,并在引号中返回每个参数。
$- 显示shell使用的当前选项。
$? 显示最后命令的推出状况。0表示没有错误。
================================================
1.得到字符串长度
☎ echo ${#variable}
☎ expr length “$variable”
☎ expr “$variable” : “.*”
e=www; a=e; echo ${!a}; eval echo \$$a
2.查找字符串子串位置
☎ expr index “$variable” “substring”
3.得到字符串子字符串
☎ echo ${variable:position:length}
☎ expr substr “$variable” startposition length
4.匹配正则表达式之匹配长度
expr match “$x” “this”
☎ expr match “$x” “string”
5.字符串的掐头去尾
☎ echo ${variable#startletter*endletter} # #表示掐头,因为键盘上#在$前面,一个表示最小匹配
☎ echo ${variable##tartletter*endletter} 两个表示最大匹配
☎ echo ${variable%startletter*endletter} # %表示去尾,因为键盘上%在$后面,一个表示最小匹配
☎ echo ${variable%%startletter*endletter} 两个表示最大匹配
6.字符(串)的替换
☎ echo ${variable/oldletter/newletter} #替换一个
☎ echo ${variable//oldletter/newletter} #替换所有
7。测试变量是否已经赋值
${variable:-value}
如果变量已经赋值,则使用该变量值。如果变量为空,则使用value。需要注意的是,value并不赋给variable。
${variable:=value}
该表达式上面的区别就是,如果variable为空,则value赋给variable。
${variable:?”customed message “}
变量是否为空,如果为空的话则显示带有系统错误信息
================================================
Bash 测试和比较函数
test expr 和 [ expr ] 是等价的。
☎ test 3 -gt 4 && echo True || echo false
false
必须用 \ 加以转义
☎ [ “abc” \< “def” ];echo $?
0
-a 和 -o 选项使用逻辑运算符 AND 和 OR
☎ [ ! \( “a” = “$HOME” -o 3 -lt 4 \) ]; echo $?
1
不需要对 (( 和 )) 之间的操作符转义
(( w=(y/x) + ( (~ ++x) & 0×0f ) )); echo $? $x $y $w
用 [[ 复合命令,进行通配符测试,包含算术测试
( -d “$HOME” ) && ( -w “$HOME” ) && echo “home is a writable directory”
“abc def d,x” == a[abc]*\ ?d* ; echo $?
| a -gt 2 ; echo $?
在 shell 中用 echo 和 $(( )) 直接进行计算
分享平时工作中那些给力的shell命令
http://zhengdl126.iteye.com/blog/834464
http://yunhaozou.org/perl-shell/162.html
SYN_RECV 1
ESTABLISHED 9
FIN_WAIT1 4
TIME_WAIT 127
关于TCP状态的变迁,可以从下图形象地看出:
状态:描述
CLOSED:无连接是活动的或正在进行
LISTEN:服务器在等待进入呼叫
SYN_RECV:一个连接请求已经到达,等待确认
SYN_SENT:应用已经开始,打开一个连接
ESTABLISHED:正常数据传输状态
FIN_WAIT1:应用说它已经完成
FIN_WAIT2:另一边已同意释放
ITMED_WAIT:等待所有分组死掉
CLOSING:两边同时尝试关闭
TIME_WAIT:另一边已初始化一个释放
LAST_ACK:等待所有分组死掉
User:root Host:PREwas01 Date:02/07/2012
------------------------------------------------------------------
1:kill node and server 15:makedump_svr1
2:start node 16:makedump_svr2
3:start server1 17:dump_high_cpu_server1
4:start server2 18:dump_high_cpu_server2
5:stop Server1 19:getGC_svr1
6:stop Server2 20:getGC_svr2
7:tailSystemOut_svr1 21:delLog_svr1
8:tailSystemOut_svr2 22:delLog_svr2
9:tailSystemErr_svr1 23:watch nmon
10:tailSystemErr_svr2 24:ps-java
11:moreSystemOut_svr1 25:vmstat
12:moreSystemOut_svr2
13:moreSystemErr_svr1
14:moreSystemErr_svr2
------------------------------------------------------------------
Your Choice [1,..,25] >
sudo ./menu.sh
#!/bin/bash #path of server Servername_1='emall02_svr1' Servername_2='emall02_svr2' Serverhomepath='/usr/IBM/WebSphere/AppServer/profiles/EMALL02' Serverbinpath='/usr/IBM/WebSphere/AppServer/profiles/EMALL02/bin' Errlogpath_1='/usr/IBM/WebSphere/AppServer/profiles/EMALL02/logs/emall02_svr1/SystemErr.log' Errlogpath_2='/usr/IBM/WebSphere/AppServer/profiles/EMALL02/logs/emall02_svr2/SystemErr.log' Outlogpath_1='/usr/IBM/WebSphere/AppServer/profiles/EMALL02/logs/emall02_svr1/SystemOut.log' Outlogpath_2='/usr/IBM/WebSphere/AppServer/profiles/EMALL02/logs/emall02_svr2/SystemOut.log' Gclogpath_1='/usr/IBM/WebSphere/AppServer/profiles/EMALL02/logs/emall02_svr1' Gclogpath_2='/usr/IBM/WebSphere/AppServer/profiles/EMALL02/logs/emall02_svr2' function kill_node_server(){ echo "kill node..." ps -ef | grep nodeagent | grep -v grep|grep -v tail|grep -v more|awk '{print $2}'|xargs kill -9 echo "kill node sucess." echo "kill server..." ps -ef | grep $Servername_1 | grep -v grep|grep -v tail|grep -v more|awk '{print $2}'|xargs kill -9 echo "kill server_1 sucess." ps -ef | grep $Servername_2 | grep -v grep|grep -v tail|grep -v more|awk '{print $2}'|xargs kill -9 echo "kill server_2 sucess." } function startNode(){ su - wcsuser << eof cd $Serverbinpath ./startNode.sh eof } function startServer1(){ su - wcsuser << eof cd $Serverbinpath ./startServer.sh $Servername_1 eof } function startServer2(){ su - wcsuser << eof cd $Serverbinpath ./startServer.sh $Servername_2 eof } function stopServer_1(){ su - wcsuser << eof cd $Serverbinpath ./stopServer.sh $Servername_1 -username configadmin -password passwdxtgl eof } function stopServer_2(){ su - wcsuser << eof cd $Serverbinpath ./stopServer.sh $Servername_2 -username configadmin -password passwdxtgl eof } function tailSystemOut_1(){ tail -f $Outlogpath_1 } function tailSystemOut_2(){ tail -f $Outlogpath_2 } function tailSystemErr_1(){ tail -f $Errlogpath_1 } function tailSystemErr_2(){ tail -f $Errlogpath_2 } function moreSystemOut_1(){ more $Outlogpath_1 } function moreSystemOut_2(){ more $Outlogpath_2 } function moreSystemErr_1(){ more $Errlogpath_1 } function moreSystemErr_2(){ more $Errlogpath_2 } function nmon(){ cd /nmon/ ./nmon_x86_rhel45 } function delLog_1(){ > $Outlogpath_1 } function delLog_2(){ > $Outlogpath_2 } function makedump_1(){ ps -ef | grep $Servername_1 |grep -v grep |grep -v tail|grep -v more|grep -v "$0"|awk '{print $2}'|xargs kill -3 mv $Serverhomepath/javacore* /home/yhpre/dumpfile/ chown yhpre.yhpre /home/yhpre/dumpfile/* } function makedump_2(){ ps -ef | grep $Servername_2 |grep -v grep |grep -v tail|grep -v more|grep -v "$0"|awk '{print $2}'|xargs kill -3 mv $Serverhomepath/javacore* /home/yhpre/dumpfile/ chown yhpre.yhpre /home/yhpre/dumpfile/* } function getnmon(){ cd /home/yhpre/nmon rm -fr *.nmon cp -a /nmon/*.nmon . chown yhpre.yhpre *.* } function dump_high_cpu_server1(){ pid=`ps -ef | grep $Servername_1 |grep -v grep|grep -v tail|grep -v more|awk '{print $2}'` top -H -p $pid -b -n1 >> /home/yhpre/dumpfile/dump_high_cpu_svr1.txt;kill -3 $pid mv $Serverhomepath/javacore* /home/yhpre/dumpfile/ chown yhpre.yhpre /home/yhpre/dumpfile/* } function dump_high_cpu_server2(){ pid=`ps -ef | grep $Servername_2 |grep -v grep|grep -v tail|grep -v more|awk '{print $2}'` top -H -p $pid -b -n1 >> /home/yhpre/dumpfile/dump_high_cpu_svr2.txt;kill -3 $pid mv $Serverhomepath/javacore* /home/yhpre/dumpfile/ chown yhpre.yhpre /home/yhpre/dumpfile/* } function getGC_svr1(){ cd /home/yhpre/dumpfile/svr1 cp -a $Gclogpath_1/verbosegc.* . chown yhpre.yhpre verbosegc.* } function getGC_svr2(){ cd /home/yhpre/dumpfile/svr2 cp -a $Gclogpath_1/verbosegc.* . chown yhpre.yhpre verbosegc.* } function makenmon(){ sh /home/yhpre/nmon.sh } function ps-java(){ ps -ef | grep java } function vmstat2(){ vmstat 2 } trap "" 2 3 15 MYDATE=`date +%d/%m/%Y` THIS_HOST=`hostname -s` USER=`whoami` while : do clear cat << eof ------------------------------------------------------------------ User:$USER Host:$THIS_HOST Date:$MYDATE ------------------------------------------------------------------ 1:kill node and server 15:makedump_svr1 2:start node 16:makedump_svr2 3:start server1 17:dump_high_cpu_server1 4:start server2 18:dump_high_cpu_server2 5:stop Server1 19:getGC_svr1 6:stop Server2 20:getGC_svr2 7:tailSystemOut_svr1 21:delLog_svr1 8:tailSystemOut_svr2 22:delLog_svr2 9:tailSystemErr_svr1 23:watch nmon 10:tailSystemErr_svr2 24:ps-java 11:moreSystemOut_svr1 25:vmstat 12:moreSystemOut_svr2 13:moreSystemErr_svr1 14:moreSystemErr_svr2 ------------------------------------------------------------------ eof echo -e -n "\tYour Choice [1,..,25] >" read CHOICE case $CHOICE in 1) kill_node_server ;; 2) startNode ;; 3) startServer1 ;; 4) startServer2 ;; 5) stopServer_1 ;; 6) stopServer_2 ;; 7) tailSystemOut_1 ;; 8) tailSystemOut_2 ;; 9) tailSystemErr_1 ;; 10) tailSystemErr_2 ;; 11) moreSystemOut_1 ;; 12) moreSystemOut_2 ;; 13) moreSystemErr_1 ;; 14) moreSystemErr_2 ;; 15) makedump_1 ;; 16) makedump_2 ;; 17) dump_high_cpu_server1 ;; 18) dump_high_cpu_server2 ;; 19) getGC_svr1 ;; 20) getGC_svr2 ;; 21) delLog_1 ;; 22) delLog_2 ;; 23) nmon ;; 24) ps-java ;; 25) vmstat2 ;; b2c_yaoyunfei) exit 0 ;; *) echo -e "\t\007unknow user response" ;; esac echo -e -n "\tPress Enter to continue" read DUMMY done
几乎所有的讲解编程的书给读者的第一个例子都是 Hello World 程序,那么我们今天也就从这个例子出发,来逐步了解 BASH。
用 vi 编辑器编辑一个 hello 文件如下:
#!/bin/bash
# This is a very simple example
echo Hello World
这样最简单的一个 BASH 程序就编写完了。这里有几个问题需要说明一下:
一,第一行的 #! 是什么意思
二,第一行的 /bin/bash 又是什么意思
三,第二行是注释吗
四,echo 语句
五,如何执行该程序
#! 是说明 hello 这个文件的类型的,有点类似于 Windows 系统下用不同文件后缀来表示不同文件类型的意思(但不相同)。linux 系统根据 "#!" 及该字串后面的信息确定该文件的类型,关于这一问题同学们回去以后可以通过 "man magic"命令 及 /usr/share/magic 文件来了解这方面的更多内容。在 BASH 中 第一行的 "#!" 及后面的 "/bin/bash" 就表明该文件是一个 BASH 程序,需要由 /bin 目录下的 bash 程序来解释执行。BASH 这个程序一般是存放在 /bin 目录下,如果你的 Linux 系统比较特别,bash 也有可能被存放在 /sbin 、/usr/local/bin 、/usr/bin 、/usr/sbin 或 /usr/local/sbin 这样的目录下;如果还找不到,你可以用 "locate bash" "find / -name bash 2> /dev/null" 或 "whereis bash" 这三个命令找出 bash 所在的位置;如果仍然找不到,那你可能需要自己动手安装一个 BASH 软件包了。
第二行的 "# This is a ..." 就是 BASH 程序的注释,在 BASH 程序中从“#”号(注意:后面紧接着是“!”号的除外)开始到行尾的多有部分均被看作是程序的注释。的三行的 echo 语句的功能是把 echo 后面的字符串输出到标准输出中去。由于 echo 后跟的是 "Hello World" 这个字符串,因此 "Hello World"这个字串就被显示在控制台终端的屏幕上了。需要注意的是 BASH 中的绝大多数语句结尾处都没有分号。
如何执行该程序呢?有两种方法:一种是显式制定 BASH 去执行:
$ bash hello 或
$ sh hello (这里 sh 是指向 bash 的一个链接,“lrwxrwxrwx 1 root root 4 Aug 20 05:41 /bin/sh -> bash”)
或者可以先将 hello 文件改为可以执行的文件,然后直接运行它,此时由于 hello 文件第一行的 "#! /bin/bash" 的作用,系统会自动用/bin/bash 程序去解释执行 hello 文件的:
$ chmod u+x hello
$ ./hello
此处没有直接 “$ hello”是因为当前目录不是当前用户可执行文件的默认目录,而将当前目录“.”设为默认目录是一个不安全的设置。
需要注意的是,BASH 程序被执行后,实际上 linux 系统是另外开设了一个进程来运行的。
变量和运算
我们先来从整体上把握一下 BASH 中变量的用法,然后再去分析 BASH 中变量使用与 C 语言中的不同。BASH 中的变量都是不能含有保留字,不能含有 "-" 等保留字符,也不能含有空格。
简单变量
在 BASH 中变量定义是不需要的,没有 "int i" 这样的定义过程。如果想用一个变量,只要他没有在前面被定义过,就直接可以用,当然你使用该变量的第一条语句应该是对他赋初值了,如果你不赋初值也没关 系,只不过该变量是空( 注意:是 NULL,不是 0 )。不给变量赋初值虽然语法上不反对,但不是一个好的编程习惯。好了我们看看下面的例子:
首先用 vi 编辑下面这个文件 hello2:
#!/bin/bash
# give the initialize value to STR
STR="Hello World"
echo $STR
在上面这个程序中我们需要注意下面几点:
一,变量赋值时,'='左右两边都不能有空格;
二,BASH 中的语句结尾不需要分号(";");
三,除了在变量赋值和在FOR循环语句头中,BASH 中的变量使用必须在变量前加"$"符号,同学们可以将上面程序中第三行改为 "echo STR" 再试试,看看会出什么结果。
四,由于 BASH 程序是在一个新的进程中运行的,所以该程序中的变量定义和赋值不会改变其他进程或原始 Shell 中同名变量的值,也不会影响他们的运行。
更细致的文档甚至提到以但引号括起来的变量将不被 BASH 解释为变量,如 '$STR' ,而被看成为纯粹的字符串。而且更为标准的变量引用方式是 ${STR} 这样的,$STR 自不过是对 ${STR} 的一种简化。在复杂情况下(即有可能产生歧义的地方)最好用带 {} 的表示方式。
BASH 中的变量既然不需要定义,也就没有类型一说,一个变量即可以被定义为一个字符串,也可以被再定义为整数。如果对该变量进行整数运算,他就被解释为整数;如果对他进行字符串操作,他就被看作为一个字符串。请看下面的例子:
#!/bin/bash
x=1999
let "x = $x + 1"
echo $x
x="olympic'"$x
echo $x
关于整数变量计算,有如下几种:" + - * / % ",他们的意思和字面意思相同。整数运算一般通过 let 和 expr 这两个指令来实现,如对变量 x 加 1 可以写作:let "x = $x + 1" 或者 x=`expr $x + 1`
在比较操作上,整数变量和字符串变量各不相同,详见下表:
对应的操作 整数操作 字符串操作
相同 -eq =
不同 -ne !=
大于 -gt >
小于 -lt <
大于或等于 -ge
小于或等于 -le
为空 -z
不为空 -n
比如:
比较字符串 a 和 b 是否相等就写作:if [ $a = $b ]
判断字符串 a 是否为空就写作: if [ -z $a ]
判断整数变量 a 是否大于 b 就写作:if [ $a -gt $b ]
更细致的文档推荐在字符串比较时尽量不要使用 -n ,而用 ! -z 来代替。(其中符号 "!" 表示求反操作)
BASH 中的变量除了用于对 整数 和 字符串 进行操作以外,另一个作用是作为文件变量。BASH 是 linux 操作系统的 Shell,因此系统的文件必然是 BASH 需要操作的重要对象,如 if [ -x /root ] 可以用于判断 /root 目录是否可以被当前用户进入。下表列出了 BASH 中用于判断文件属性的操作符:
运算符 含义( 满足下面要求时返回 TRUE )
-e file 文件 file 已经存在
-f file 文件 file 是普通文件
-s file 文件 file 大小不为零
-d file 文件 file 是一个目录
-r file 文件 file 对当前用户可以读取
-w file 文件 file 对当前用户可以写入
-x file 文件 file 对当前用户可以执行
-g file 文件 file 的 GID 标志被设置
-u file 文件 file 的 UID 标志被设置
-O file 文件 file 是属于当前用户的
-G file 文件 file 的组 ID 和当前用户相同
file1 -nt file2 文件 file1 比 file2 更新
file1 -ot file2 文件 file1 比 file2 更老
注意:上表中的 file 及 file1、file2 都是指某个文件或目录的路径。
关于局部变量
在 BASH 程序中如果一个变量被使用了,那么直到该程序的结尾,该变量都一直有效。为了使得某个变量存在于一个局部程序块中,就引入了局部变量的概念。BASH 中,在变量首次被赋初值时加上 local 关键字就可以声明一个局部变量,如下面这个例子:
#!/bin/bash
HELLO=Hello
function hello {
local HELLO=World
echo $HELLO
}
echo $HELLO
hello
echo $HELLO
该程序的执行结果是:
Hello
World
Hello
这个执行结果表明全局变量 $HELLO 的值在执行函数 hello 时并没有被改变。也就是说局部变量 $HELLO 的影响只存在于函数那个程序块中。
BASH 中的变量与 C 语言中变量的区别
这里我们为原来不熟悉 BASH 编程,但是非常熟悉 C 语言的程序员总结一下在 BASH 环境中使用变量需要注意的问题。
1,BASH 中的变量在引用时都需要在变量前加上 "$" 符号( 第一次赋值及在For循环的头部不用加 "$"符号 );
2,BASH 中没有浮点运算,因此也就没有浮点类型的变量可用;
3,BASH 中的整形变量的比较符号与 C 语言中完全不同,而且整形变量的算术运算也需要经过 let 或 expr 语句来处理;
[目录]
--------------------------------------------------------------------------------
输入输出
关于输入、输出和错误输出
在字符终端环境中,标准输入/标准输出的概念很好理解。输入即指对一个应用程序或命令的输入,无论是从键盘输入还是从别的文件输入;输出即指应用 程序或命令产生的一些信息;与 Windows 系统下不同的是,linux 系统下还有一个标准错误输出的概念,这个概念主要是为程序调试和系统维护目的而设置的,错误输出于标准输出分开可以让一些高级的错误信息不干扰正常的输出 信息,从而方便一般用户的使用。
在 linux 系统中:标准输入(stdin)默认为键盘输入;标准输出(stdout)默认为屏幕输出;标准错误输出(stderr)默认也是输出到屏幕(上面的 std 表示 standard)。在 BASH 中使用这些概念时一般将标准输出表示为 1,将标准错误输出表示为 2。下面我们举例来说明如何使用他们,特别是标准输出和标准错误输出。
输入、输出及标准错误输出主要用于 I/O 的重定向,就是说需要改变他们的默认设置。先看这个例子:
$ ls > ls_result
$ ls -l >> ls_result
上面这两个命令分别将 ls 命令的结果输出重定向到 ls_result 文件中和追加到 ls_result 文件中,而不是输出到屏幕上。">"就是输出(标准输出和标准错误输出)重定向的代表符号,连续两个 ">" 符号,即 ">>" 则表示不清除原来的而追加输出。下面再来看一个稍微复杂的例子:
$ find /home -name lost* 2> err_result
这个命令在 ">" 符号之前多了一个 "2","2>" 表示将标准错误输出重定向。由于 /home 目录下有些目录由于权限限制不能访问,因此会产生一些标准错误输出被存放在 err_result 文件中。大家可以设想一下 find /home -name lost* 2>>err_result 命令会产生什么结果?
如果直接执行 find /home -name lost* > all_result ,其结果是只有标准输出被存入 all_result 文件中,要想让标准错误输出和标准输入一样都被存入到文件中,那该怎么办呢?看下面这个例子:
$ find /home -name lost* > all_result 2>& 1
上面这个例子中将首先将标准错误输出也重定向到标准输出中,再将标准输出重定向到 all_result 这个文件中。这样我们就可以将所有的输出都存储到文件中了。为实现上述功能,还有一种简便的写法如下:
$ find /home -name lost* >& all_result
如果那些出错信息并不重要,下面这个命令可以让你避开众多无用出错信息的干扰:
$ find /home -name lost* 2> /dev/null
同学们回去后还可以再试验一下如下几种重定向方式,看看会出什么结果,为什么?
$ find /home -name lost* > all_result 1>& 2
$ find /home -name lost* 2> all_result 1>& 2
$ find /home -name lost* 2>& 1 > all_result
另外一个非常有用的重定向操作符是 "-",请看下面这个例子:
$ (cd /source/directory && tar cf - . ) | (cd /dest/directory && tar xvfp -)
该命令表示把 /source/directory 目录下的所有文件通过压缩和解压,快速的全部移动到 /dest/directory 目录下去,这个命令在 /source/directory 和 /dest/directory 不处在同一个文件系统下时将显示出特别的优势。
下面还几种不常见的用法:
n<&- 表示将 n 号输入关闭
<&- 表示关闭标准输入(键盘)
n>&- 表示将 n 号输出关闭
>&- 表示将标准输出关闭
[目录]
--------------------------------------------------------------------------------
流程控制
BASH 中的基本流程控制语法
BASH 中几乎含有 C 语言中常用的所有控制结构,如条件分支、循环等,下面逐一介绍。
if...then...else
if 语句用于判断和分支,其语法规则和 C 语言的 if 非常相似。其几种基本结构为:
if [ expression ]
then
statments
fi
或者
if [ expression ]
then
statments
else
statments
fi
或者
if [ expression ]
then
statments
else if [ expression ]
then
statments
else
statments
fi
或者
if [ expression ]
then
statments
elif [ expression ]
then
statments
else
statments
fi
值得说明的是如果你将 if 和 then 简洁的写在一行里面,就必须在 then 前面加上分号,如:if [ expression ]; then下面这个例子说明了如何使用 if 条件判断语句:
#!/bin/bash
if [ $1 -gt 90 ]
then
echo "Good, $1"
elif [ $1 -gt 70 ]
then
echo "OK, $1"
else
echo "Bad, $1"
fi
exit 0
上面例子中的 $1 是指命令行的第一个参数,这个会在后面的“BASH 中的特殊保留字”中讲解。
for
for 循环结构与 C 语言中有所不同,在 BASH 中 for 循环的基本结构是:
for $var in [list]
do
statments
done
其中 $var 是循环控制变量,[list] 是 $var 需要遍历的一个集合,do/done 对包含了循环体,相当于 C 语言中的一对大括号。另外如果do 和 for 被写在同一行,必须在 do 前面加上 ";"。如: for $var in [list]; do 。下面是一个运用 for 进行循环的例子:
#!/bin/bash
for day in Sun Mon Tue Wed Thu Fri Sat
do
echo $day
done
# 如果列表被包含在一对双引号中,则被认为是一个元素
for day in "Sun Mon Tue Wed Thu Fri Sat"
do
echo $day
done
exit 0
注意上面的例子中,在 for 所在那行的变量 day 是没有加 "$" 符号的,而在循环体内,echo 所在行变量 $day 是必须加上 "$" 符号的。另外如果写成 for day 而没有后面的 in [list] 部分,则 day 将取遍命令行的所有参数。如这个程序:
#!/bin/bash
for param
do
echo $param
done
exit 0
上面这个程序将列出所有命令行参数。for 循环结构的循环体被包含在 do/done 对中,这也是后面的 while、until 循环所具有的特点。
while
while 循环的基本结构是:
while [ condition ]
do
statments
done
这个结构请大家自己编写一个例子来验证。
# /bin/bash # 循环10遍后停止 i=1 while [ $i -le 10 ] do xxxx 命令 sleep 10 let i++ done
until
until 循环的基本结构是:
until [ condition is TRUE ]
do
statments
done
这个结构也请大家自己编写一个例子来验证。
case
BASH 中的 case 结构与 C 语言中的 switch 语句的功能比较类似,可以用于进行多项分支控制。其基本结构是:
case "$var" in
condition1 )
statments1;;
condition2 )
statments2;;
...
* )
default statments;;
esac
下面这个程序是运用 case 结构进行分支执行的例子:
#!/bin/bash
echo "Hit a key, then hit return."
read Keypress
case "$Keypress" in
[a-z] ) echo "Lowercase letter";;
[A-Z] ) echo "Uppercase letter";;
[0-9] ) echo "Digit";;
* ) echo "Punctuation, whitespace, or other";;
esac
exit 0
上面例子中的第四行 "read Keypress" 一句中的 read 语句表示从键盘上读取输入。这个命令将在本讲义的 BASH 的其他高级问题中讲解。
break/continue
熟悉 C 语言编程的都很熟悉 break 语句和 continue 语句。BASH 中同样有这两条语句,而且作用和用法也和 C 语言中相同,break 语句可以让程序流程从当前循环体中完全跳出,而 continue 语句可以跳过当次循环的剩余部分并直接进入下一次循环。
[目录]
--------------------------------------------------------------------------------
函数
函数的使用
BASH 是一个相对简单的脚本语言,不过为了方便结构化的设计,BASH 中也提供了函数定义的功能。BASH 中的函数定义很简单,只要向下面这样写就可以了:
function my_funcname {
code block
}
或者
my_funcname() {
code block
}
上面的第二种写法更接近于 C 语言中的写法。BASH 中要求函数的定义必须在函数使用之前,这是和 C 语言用头文件说明函数方法的不同。
更进一步的问题是如何给函数传递参数和获得返回值。BASH 中函数参数的定义并不需要在函数定义处就制定,而只需要在函数被调用时用 BASH 的保留变量 $1 $2 ... 来引用就可以了;BASH 的返回值可以用 return 语句来指定返回一个特定的整数,如果没有 return 语句显式的返回一个返回值,则返回值就是该函数最后一条语句执行的结果(一般为 0,如果执行失败返回错误码)。函数的返回值在调用该函数的程序体中通过 $? 保留字来获得。下面我们就来看一个用函数来计算整数平方的例子:
#!/bin/bash
square() {
let "res = $1 * $1"
return $res
}
square $1
result=$?
echo $result
exit 0
[目录]
--------------------------------------------------------------------------------
bash快捷键
关于bash在控制台下的快捷键
ctrl+u 删除光标以前的所有字符
ctrl+d 删除光标以前的一个字符
ctrl+k 删除光标以后的所有字符
ctrl+h 删除光标以后的一个字符
ctrl+t 调换光标前两个字符的次序
ctrl+a 移动光标到最前面
ctrl+e 移动光标到最后面
ctrl+p 上一个命令
ctrl+n 下一个命令
ctrl+s 锁定输入
ctrl+q 解除锁定
ctrl+f 移动光标到后一个字符
ctrl+b 移动光标到前一个字符
ctrl+x 标记一个位置
ctrl+c 清除当前的输入
[目录]
--------------------------------------------------------------------------------
gawk
awk是一种程序语言,对文档资料的处理具有很强的功能。awk名称是由它三个最初设计者的姓氏的第一个字母而命名的:AlfredV.Aho、PeterJ.Weinberger、BrianW.Kernighan。
awk最初在1977年完成。1985年发表了一个新版本的awk,它的功能比旧版本增强了不少。awk能够用很短的程序对文档里的资料做修改、 比较、提取、打印等处理。如果使用C或Pascal等语言代码编写完成上述的任务会十分不方便而且很花费时间,所写的程序也会很大。
awk不仅仅是一个编程语言,它还是linux系统管理员和程序员的一个不可缺少的工具。
awk语言本身十分好学,易于掌握,并且特别的灵活。
gawk是GNU计划下所做的awk,gawk最初在1986年完成,之后不断地被改进、更新。gawk包含awk的所有功能。
基本上有两种方法可以执行gawk程序。
如果gawk程序很短,则可以将gawk直接写在命令行,如下所示:
gawk'program'input-file1input-file2...
其中program包括一些pattern和action。
如果gawk程序较长,较为方便的做法是将gawk程序存在一个文件中,gawk的格式如下所示:
gawk-fprogram-fileinput-file1input-file2...
gawk程序的文件不止一个时,执行gawk的格式如下所示:
gawk-fprogram-file1-fprogram-file2...input-file1input-file2...
[目录]
--------------------------------------------------------------------------------
文件、记录和字段
一般情况下,gawk可以处理文件中的数值数据,但也可以处理字符串信息。如果数据没有存储在文件中,可以通过管道命令和其他的重定向方法给 gawk提供输入。当然,gawk只能处理文本文件(ASCII码文件)。电话号码本就是一个gawk可以处理的文件的简单例子。电话号码本由很多条目组 成,每一个条目都有同样的格式:姓、名、地址、电话号码。每一个条目都是按字母顺序排列。
在gawk中,每一个这样的条目叫做一个记录。它是一个完整的数据的集合。例如,电话号码本中的SmithJohn这个条目,包括他的地址和电话 号码,就是一条记录。记录中的每一项叫做一个字段。在gawk中,字段是最基本的单位。多个记录的集合组成了一个文件。大多数情况下,字段之间由一个特殊 的字符分开,像空格、TAB、分号等。这些字符叫做字段分隔符。请看下面这个/etc/passwd文件:
tparker;t36s62hsh;501;101;TimParker;/home/tparker;/bin/bash
etreijs;2ys639dj3h;502;101;EdTreijs;/home/etreijs;/bin/tcsh
ychow;1h27sj;503;101;YvonneChow;/home/ychow;/bin/bash
你可以看出/etc/passwd文件使用分号作为字段分隔符。/etc/passwd文件中的每一行都包括七个字段:用户名;口令;用户ID; 工作组 ID;注释;home目录;启始的外壳。如果你想要查找第六个字段,只需数过五个分号即可。但考虑到以下电话号码本的例子,你就会发现一些问题:
SmithJohn13WilsonSt.555-1283
SmithJohn2736ArtsideDrApt123555-2736
SmithJohn125WestmountCr555-1726
虽然我们能够分辨出每个记录包括四个字段,但gawk却无能为力。电话号码本使用空格作为分隔符,所以gawk认为Smith是第一个字 段,John是第二个字段,13是第三个字段,依次类推。就gawk而言,如果用空格作为字段分隔符的话,则第一个记录有六个字段,而第二个记录有八个字 段。所以,我们必须找出一个更好的字段分隔符。例如,像下面一样使用斜杠作为字段分隔符:
Smith/John/13WilsonSt./555-1283
Smith/John/2736ArtsideDr/Apt/123/555-2736
Smith/John/125WestmountCr/555-1726
如果你没有指定其他的字符作为字段分隔符,那么gawk将缺省地使用空格或TAB作为字段分隔符。
[目录]
--------------------------------------------------------------------------------
模式和动作
在gawk语言中每一个命令都由两部分组成:一个模式(pattern)和一个相应的动作(action)。只要模式符合,gawk就会执行相应的动作。其中模式部分用两个斜杠括起来,而动作部分用一对花括号括起来。例如:
/pattern1/{action1}
/pattern2/{action2}
/pattern3/{action3}
所有的gawk程序都是由这样的一对对的模式和动作组成的。其中模式或动作都能够被省略,但是两个不能同时被省略。如果模式被省略,则对于作为输入的文件里面的每一行,动作都会被执行。如果动作被省略,则缺省的动作被执行,既显示出所有符合模式的输入行而不做任何的改动。
下面是一个简单的例子,因为gawk程序很短,所以将gawk程序直接写在外壳命令行:
gawk'/tparker/'/etc/passwd
此程序在上面提到的/etc/passwd文件中寻找符合tparker模式的记录并显示(此例中没有动作,所以缺省的动作被执行)。
让我们再看一个例子:
gawk'/UNIX/{print$2}'file2.data
此命令将逐行查找file2.data文件中包含UNIX的记录,并打印这些记录的第二个字段。
你也可以在一个命令中使用多个模式和动作对,例如:
gawk'/scandal/{print$1}/rumor/{print$2}'gossip_file
此命令搜索文件gossip_file中包括scandal的记录,并打印第一个字段。然后再从头搜索gossip_file中包括rumor的记录,并打印第二个字段。
[目录]
--------------------------------------------------------------------------------
运算
gawk有很多比较运算符,下面列出重要的几个:
==相等
!=不相等
>大于
<小于
>=大于等于
<=小于等于
例如:gawk'$4>100'testfile将会显示文件testfile中那些第四个字段大于100的记录。
下表列出了gawk中基本的数值运算符。
运算符说明示例
+加法运算2+6
-减法运算6-3
*乘法运算2*5
/除法运算8/4
^乘方运算3^2(=9)
%求余数9%4(=1)
例如:{print$3/2}显示第三个字段被2除的结果。
在gawk中,运算符的优先权和一般的数学运算的优先权一样。例如:{print$1+$2*$3}显示第二个字段和第三个字段相乘,然后和第一 个字段相加的结果。你也可以用括号改变优先次序。例如:{print($1+$2)*$3}显示第一个字段和第二个字段相加,然后和第三个字段相乘的结 果。
[目录]
--------------------------------------------------------------------------------
内部函数
gawk中有各种的内部函数,现在介绍如下:
sqrt(x)求x的平方根
sin(x)求x的正弦函数
cos(x)求x的余弦函数
atan2(x,y)求x/y的余切函数
log(x)求x的自然对数
exp(x)求x的e次方
int(x)求x的整数部分
rand()求0和1之间的随机数
srand(x)将x设置为rand()的种子数
index(in,find)在字符串in中寻找字符串find第一次出现的地方,返回值是字符串find出现在字符串in里面的位置。如果在字符串in里面找不到字符串find,则返回值为0。
例如:printindex("peanut","an")
显示结果3。
length(string)求出string有几个字符。
例如:length("abcde")
显示结果5。
match(string,regexp)在字符串string中寻找符合regexp的最长、最靠左边的子字符串。返回值是regexp在 string 的开始位置,即index值。match函数将会设置系统变量RSTART等于index的值,系统变量RLENGTH等于符合的字符个数。如果不符合, 则会设置RSTART为0、RLENGTH为-1。
sprintf(format,expression1,...)和printf类似,但是sprintf并不显示,而是返回字符串。
例如:sprintf("pi=%.2f(approx.)",22/7)
返回的字符串为pi=3.14(approx.)
sub(regexp,replacement,target)在字符串target中寻找符合regexp的最长、最靠左的地方,以字串replacement代替最左边的regexp。
例如:
str="water,water,everywhere"
sub(/at/,"ith",str)
结果字符串str会变成
wither,water,everywhere
gsub(regexp,replacement,target)与前面的sub类似。在字符串target中寻找符合regexp的所有地方,以字符串replacement代替所有的regexp。
例如:str="water,water,everywhere"
gsub(/at/,"ith",str)
结果字符串str会变成
wither,wither,everywhere
substr(string,start,length)返回字符串string的子字符串,这个子字符串的长度为length,从第start个位置开始。
例如:substr("washington",5,3)返回值为ing如果没有length,则返回的子字符串是从第start个位置开始至结束。
例如:substr("washington",5)
返回值为ington。
tolower(string)将字符串string的大写字母改为小写字母。
例如:tolower("MiXeDcAsE123")
返回值为mixedcase123。
toupper(string)将字符串string的小写字母改为大写字母。
例如:toupper("MiXeDcAsE123")
返回值为MIXEDCASE123。
输入输出的内部函数
close(filename)将输入或输出的文件filename关闭。
system(command)此函数允许用户执行操作系统的指令,执行完毕后将回到gawk程序。
例如:BEGIN{system("ls")}
[目录]
--------------------------------------------------------------------------------
字符串和数字
字符串就是一连串的字符,它可以被gawk逐字地翻译。字符串用双引号括起来。数字不能用双引号括起来,并且gawk将它当作一个数值。
例如:gawk'$1!="Tim"{print}'testfile
此命令将显示第一个字段和Tim不相同的所有记录。如果命令中Tim两边不用双引号,gawk将不能正确执行。
再如:gawk'$1=="50"{print}'testfile
此命令将显示所有第一个字段和50这个字符串相同的记录。gawk不管第一字段中的数值的大小,而只是逐字地比较。这时,字符串50和数值50并不相等。
我们可以让动作显示一些比较复杂的结果。例如:
gawk'$1!="Tim"{print$1,$5,$6,$2}'testfile
你也可以使用一些换码控制符格式化整行的输出。之所以叫做换码控制符,是因为gawk对这些符号有特殊的解释。下面列出常用的换码控制符:
a警告或响铃字符。
后退一格。
f换页。
换行。
回车。
Tab。
v垂直的tab。
在gawk中,缺省的字段分隔符一般是空格符或TAB。但你可以在命令行使用-F选项改变字符分隔符,只需在-F后面跟着你想用的分隔符即可。
gawk-F";"'/tparker/{print}'/etc/passwd
在此例中,你将字符分隔符设置成分号。注意:-F必须是大写的,而且必须在第一个引号之前。
[目录]
--------------------------------------------------------------------------------
元字符
gawk语言在格式匹配时有其特殊的规则。例如,cat能够和记录中任何位置有这三个字符的字段匹配。但有时你需要一些更为特殊的匹配。如果你想让cat只和concatenate匹配,则需要在格式两端加上空格:
/cat/{print}
再例如,你希望既和cat又和CAT匹配,则可以使用或(|):
/cat|CAT/{print}
在gawk中,有几个字符有特殊意义。下面列出可以用在gawk格式中的这些字符:
?^表示字段的开始。
例如:
$3~/^b/
如果第三个字段以字符b开始,则匹配。
?$表示字段的结束。
例如:
$3~/b$/
如果第三个字段以字符b结束,则匹配。
?.表示和任何单字符m匹配。
例如:
$3~/i.m/
如果第三个字段有字符i,则匹配。
?|表示“或”。
例如:
/cat|CAT/
和cat或CAT字符匹配。
?*表示字符的零到多次重复。
例如:
/UNI*X/
和UNX、UNIX、UNIIX、UNIIIX等匹配。
?+表示字符的一次到多次重复。
例如:
/UNI+X/
和UNIX、UNIIX等匹配。
?{a,b}表示字符a次到b次之间的重复。
例如:
/UNI{1,3}X
和UNIX、UNIIX和UNIIIX匹配。
??表示字符零次和一次的重复。
例如:
/UNI?X/
和UNX和UNIX匹配。
?[]表示字符的范围。
例如:
/I[BDG]M/
和IBM、IDM和IGM匹配
?[^]表示不在[]中的字符。
例如:
/I[^DE]M/
和所有的以I开始、M结束的包括三个字符的字符串匹配,除了IDM和IEM之外。
[目录]
--------------------------------------------------------------------------------
调用gawk程序
当需要很多对模式和动作时,你可以编写一个gawk程序(也叫做gawk脚本)。在gawk程序中,你可以省略模式和动作两边的引号,因为在gawk程序中,模式和动作从哪开始和从哪结束时是很显然的。
你可以使用如下命令调用gawk程序:
gawk-fscriptfilename
此命令使gawk对文件filename执行名为script的gawk程序。
如果你不希望使用缺省的字段分隔符,你可以在f选项后面跟着F选项指定新的字段分隔符(当然你也可以在gawk程序中指定),例如,使用分号作为字段分隔符:
gawk-fscript-F";"filename
如果希望gawk程序处理多个文件,则把各个文件名罗列其后:
gawk-fscriptfilename1filename2filename3...
缺省情况下,gawk的输出将送往屏幕。但你可以使用linux的重定向命令使gawk的输出送往一个文件:
gawk-fscriptfilename>save_file
[目录]
--------------------------------------------------------------------------------
BEGIN和END
有两个特殊的模式在gawk中非常有用。BEGIN模式用来指明gawk开始处理一个文件之前执行一些动作。BEGIN经常用来初始化数值,设置参数等。END模式用来在文件处理完成后执行一些指令,一般用作总结或注释。
BEGIN和END中所有要执行的指令都应该用花括号括起来。BEGIN和END必须使用大写。
请看下面的例子:
BEGIN{print"Startingtheprocessthefile"}
$1=="UNIX"{print}
$2>10{printf"Thislinehasavalueof%d",$2}
END{print"Finishedprocessingthefile.Bye!"}
此程序中,先显示一条信息:Startingtheprocessthefile,然后将所有第一个字段等于UNIX的整条记录显示出来,然后再显示第二个字段大于10的记录,最后显示信息:Finished processingthefile.Bye!。
[目录]
--------------------------------------------------------------------------------
变量
在gawk中,可以用等号(=)给一个变量赋值:
var1=10
在gawk中,你不必事先声明变量类型。
请看下面的例子:
$1=="Plastic"{count=count+1}
如果第一个字段是Plastic,则count的值加1。在此之前,我们应当给count赋予过初值,一般是在BEGIN部分。
下面是比较完整的例子:
BEGIN{count=0}
$5=="UNIX"{count=count+1}
END{printf"%doccurrencesofUNIXwerefound",count}
变量可以和字段和数值一起使用,所以,下面的表达式均为合法:
count=count+$6
count=$5-8
count=$5+var1
变量也可以是格式的一部分,例如:
$2>max_value{print"Maxvalueexceededby",$2-max_value}
$4-var1
gawk语言中有几个十分有用的内置变量,现在列于下面:
NR已经读取过的记录数。
FNR从当前文件中读出的记录数。
FILENAME输入文件的名字。
FS字段分隔符(缺省为空格)。
RS记录分隔符(缺省为换行)。
OFMT数字的输出格式(缺省为%g)。
OFS输出字段分隔符。
ORS输出记录分隔符。
NF当前记录中的字段数。
如果你只处理一个文件,则NR和FNR的值是一样的。但如果是多个文件,NR是对所有的文件来说的,而FNR则只是针对当前文件而言。
例如:
NR<=5{print"Notenoughfieldsintherecord"}
检查记录数是否小于5,如果小于5,则显示出错信息。
FS十分有用,因为FS控制输入文件的字段分隔符。例如,在BEGIN格式中,使用如下的命令:
FS=":"
[目录]
--------------------------------------------------------------------------------
控制结构
if表达式
if表达式的语法如下:
if(expression){
commands
}
else{
commands
}
例如:
#asimpleifloop
(if($1==0){
print"This cell has a value of zero"
}
else{
printf"The value is %d ",$1
})
再看下一个例子:
#anicely form attedi floop
(if($1>$2){
print"The first column is larger"
}
else{
print"The second column is larger"
})
while循环
while循环的语法如下:
while(expression){
commands
}
例如:
#interest calculation computes compound interest
#inputs from a file arethea mount,interest_rateandyears
{var=1
while(var<=$3){
printf("%f ",$1*(1+$2)^var)
var++
for循环
for循环的语法如下:
for(initialization;expression;increment){
command
}
例如:
#interest calculation computes compound interest
#inputs from a fil earethea mount,interest_rateandyears
{for(var=1;var<=$3;var++){
printf("%f ",$1*(1+$2)^var)
}}
next和exit
next指令用来告诉gawk处理文件中的下一个记录,而不管现在正在做什么。语法如下:
{command1
command2
command3
next
command4
}
程序只要执行到next指令,就跳到下一个记录从头执行命令。因此,本例中,command4指令永远不会被执行。
程序遇到exit指令后,就转到程序的末尾去执行END,如果有END的话。
[目录]
--------------------------------------------------------------------------------
数组
gawk语言支持数组结构。数组不必事先初始化。声明一个数组的方法如下:
arrayname[num]=value
请看下面的例子:
#reverse lines in a file
{line[NR]=$0} #remember each line
END{var=NR #output lines in reverse order
while(var>0){
printline[var]
var--
}
此段程序读取一个文件的每一行,并用相反的顺序显示出来。我们使用NR作为数组的下标来存储文件的每一条记录,然后在从最后一条记录开始,将文件逐条地显示出来。
[目录]
--------------------------------------------------------------------------------
自定义函数
用户自定义函数
复杂的gawk程序常常可以使用自己定义的函数来简化。调用用户自定义函数与调用内部函数的方法一样。函数的定义可以放在gawk程序的任何地方。
用户自定义函数的格式如下:
functionname(parameter-list){
body-of-function
}
name是所定义的函数的名称。一个正确的函数名称可包括一序列的字母、数字、下标线(underscores),但是不可用数字做开头。 parameter-list是函数的全部参数的列表,各个参数之间以逗点隔开。body-of-function包含gawk的表达式,它是函数定义里 最重要的部分,它决定函数实际要做的事情。
下面这个例子,会将每个记录的第一个字段的值的平方与第二个字段的值的平方加起来。
{print"sum=",SquareSum($1,$2)}
function SquareSum(x,y){
sum=x*x+y*y
returnsum
}
[目录]
--------------------------------------------------------------------------------
几个实例
最后,再举几个gawk的例子:
gawk'{if(NF>max)max=NF}
END{printmax}'
此程序会显示所有输入行之中字段的最大个数。
gawk'length($0)>80'
此程序会显示出超过80个字符的每一行。此处只有模式被列出,动作是采用缺省值显示整个记录。
gawk'NF>0'
显示拥有至少一个字段的所有行。这是一个简单的方法,将一个文件里的所有空白行删除。
gawk'BEGIN{for(i=1;i<=7;i++)
printint(101*rand())}'
此程序会显示出范围是0到100之间的7个随机数。
ls-lfiles|gawk'{x+=$4};END{print"totalbytes:"x}'
此程序会显示出所有指定的文件的总字节数。
expandfile|gawk'{if(x END{print"maximumlinelengthis"x}'
此程序会将指定文件里最长一行的长度显示出来。expand会将tab改成space,所以是用实际的右边界来做长度的比较。
gawk'BEGIN{FS=":"}
{print$1|"sort"}'/etc/passwd
此程序会将所有用户的登录名称,依照字母的顺序显示出来。
gawk'{nlines++}
END{printnlines}'
此程序会将一个文件的总行数显示出来。
gawk'END{printNR}'
此程序也会将一个文件的总行数显示出来,但是计算行数的工作由gawk来做。
gawk'{printNR,$0}'
此程序显示出文件的内容时,会在每行的最前面显示出行号,它的函数与‘cat-n’类似。
[目录]
--------------------------------------------------------------------------------
Perl
Perl的基本特点
“别期望在一刻钟内就能领略Perl的所有神奇之处,这种情况很像吃香蕉,用不着吃完整只香蕉后才知其味,每咬一口都是享受,并促使你再咬下 一口,再下一口。”上面这段话是Perl项目发起人劳利·华尔(LarryWall)对学习Perl语言的一段经典评论,希望大家都能找到这种感觉。
Perl的设计目标是帮助UNIX用户完成一些常见的任务,这些任务对于Shell来说过于沉重或对移植性要求过于严格。Perl语言中包含 了C、 C++、shell,script、sed、awk这几个语言的语法,它最初的目的就是用来取代UNIX中sed/awk与脚本语言的组合,用来汇整信 息,产生报表。因此Perl语言要远远比前面讲的BASH复杂和功能强大。Perl的设计原则或者说Perl的设计哲学是以实用为第一优先,也就是力图使 Perl语言容易使用、有效率、而且完整。
Perl是按GNUPublicLicense和ArticticLicense两种许可证形式分发的,其实质是开源软件、自由软件的,原先 运行于 UNIX和类UNIX系统,现在已可以方便地在OS/2,Windows9x,Windows/NT等系统下运行。Perl是一种解释运行的语言,和 BASH程序一样,一般Perl程序的第一行需注明自己是一个Perl程序而不是Shell程序,所以一般将下面一行语句:
#!/usr/bin/perl 作为文件的第一行。
Perl由于引入了模块的设计思想,随着版本的改进,功能越来越强。现在Perl的功能已经超乎原先设计时的想象,几乎任何事都可以做到,也 变成每一部工作站必备的标准工具了。Perl最为著名的一点就是他对字符串的处理,由于Internet对文字信息处理的巨大需求,使得Perl的应用如 日中天,而且Perl语言也的确是一个非常优秀的文字信息处理语言。
一个有用的Perl程序可以很短。例如希望更换大量文件中的一些相同内容,可以使用下面的一条命令:
perl-e's/gopher/WorldWideWeb/gi'-p-i.bak*.html
下面是一个基本的perl程序:
#!/usr/local/bin/perl
#
#Programtodotheobvious
print'Helloworld.';#只是简单地显示出Helloworld.字符串。
[目录]
--------------------------------------------------------------------------------
变量
Perl中有三种变量:标量,数组(列表)和相关数组。
Perl中最基本的变量类型是标量。标量既可以是数字,也可以是字符串,而且两者是可以互换的。具体是数字还是字符串,可以有上下文决定。标量变量的语法为$variable_name。例如:
$priority=9;
把9赋予标量变量$priority,你也可以将字符串赋予该变量:
$priority='high';
注意在Perl中,变量名的大小写是敏感的,所以$a和$A是不同的变量。
以下的数值或字符串都可以赋给标量:
12312.45E-100xff(hex)0377(octal)
'Whatyou$seeis(almost)what youget''Don'tWalk'
"Howareyou?""Substitutevaluesof$xand in"quotes."
`date``uptime-u``du-sk$filespec|sort-n`
$x$list_of_things[5]$lookup{'key'}
从上面可以看出,Perl中有三种类型的引用。双引号("")括起来的字符串中的任何标量和特殊意义的字符都将被Perl解释。如果不想让 Perl解释字符串中的任何标量和特殊意义的字符,应该将字符串用单括号括起来。这时,Perl不解释其中的任何字符,除了\和'。最后,可以用(`)将 命令括起来,这样,其中的命令可以正常运行,并能得到命令的返回值。请看下面的例子:
1#!/usr/bin/perl
2$folks="100";
3print"$folks=$folks ";
4print'$folks=$folks ';
5print" BEEP!aLSOMEBLANKELINESHERE ";
6$date=`date+%D`;
7print"Todayis[$date] ";
8chop$date;
9print"Dateafterchoppingoffcarriagereturn:[".$date."] ";
注意实际程序中不应该包括行号。其输出结果如下:
$folks=100
$folks=$folks
BEEP!someblankLINESHERE
Todayis[03/29/96]
Dateafterchoppingoffcarriagereturn:[03/29/96]
第3行显示$folks的值。$之前必须使用换码符,以便Perl显示字符串$folks而不是$folks的值100。
第4行使用的是单引号,结果Perl不解释其中的任何内容,只是原封不动地将字符串显示出来。
第6行使用的是(`),则date+%D命令的执行结果存储在标量$date中。
上例中使用了一些有特殊意义的字符,下面列出这些字符的含义:
换行。
回车。
制表符。
a蜂鸣声。
Backspace。
LE将L和E之间的字符转换成小写。
l将其后的字符转换成小写。
UE将U和E之间的字符转换成大写。
u将其后的字符转换成大写。
cC插入控制字符C。
x##十六进制数##。
ooo八进制数ooo。
\反斜杠。
按原样输出下一个字符,例如:$输出$。
Perl中的数字是以浮点形式存储的。下面列出有关的数字运算符:
$a=1+2;#1加2,结果存储在$a中。
$a=3-4;#3减4,结果存储在$a中。
$a=5*6;#5乘6,结果存储在$a中。
$a=7/8;#7除以8,结果存储在$a中。
$a=9**10;#9的10次方,结果存储在$a中。
$a=5%2;#取5除2的余数,结果存储在$a中。
++$a;#$a加1,然后赋予$a。
$a++;#先将$a返回,然后$a加1。
--$a;#$a减1,然后赋予$a。
$a--;#先将$a返回,然后$a减1。
Perl支持的逻辑运算符:
$r=$x||$y$r=$x或$y。
$r=$x&&$y$r=$x与$y。
$r=!$x$r=非$x。
对于字符标量,Perl支持下面的运算符:
$a=$b.$c;#将$b和$c连接,然后赋予$a。
$a=$bx$c;#$b重复$c次,然后赋予$a。
下面是Perl中的赋值方法:
$a=$b;#将$b赋予$a。
$a+=$b;#$b加$a,然后赋予$a。
$$a-=$b;#$a减$b,然后赋予$a。
$a.=$b;#把$b连接到$a的后面,然后赋予$a。
你也可以使用下面的比较运算符:
$x==$y如果$x和$y相等,则返回真。
$x!=$y如果$x和$y不相等,则返回真。
$x<$y如果$x比$y小,则返回真。
$x<=$y如果$x小于等于$y,则返回真。
$x>$y如果$x比$y大,则返回真。
$x>=$y如果$x大于等于$y,则返回真。
$xeq$y如果字符串$x和字符串$y相同,则返回真。
数组
数组也叫做列表,是由一系列的标量组成的。数组变量以@开头。请看以下的赋值语句:
@food=("apples","pears","eels");
@music=("whistle","flute");
数组的下标从0开始,你可以使用方括号引用数组的下标:
$food[2]
返回eels。注意@已经变成了$,因为eels是一个标量。
在Perl中,数组有多种赋值方法,例如:
@moremusic=("organ",@music,"harp");
@moremusic=("organ","whistle","flute","harp");
还有一种方法可以将新的元素增加到数组中:
push(@food,"eggs");
把eggs增加到数组@food的末端。要往数组中增加多个元素,可以使用下面的语句:
push(@food,"eggs","lard");
push(@food,("eggs","lard"));
push(@food,@morefood);
push返回数组的新长度。
pop用来将数组的最后一个元素删除,并返回该元素。例如:
@food=("apples","pears","eels");
$grub=pop(@food);#此时$grub="eels"
请看下面的例子:
1#!/usr/bin/perl
2#
3#AnexampletoshowhowarraysworkinPerl
4#
5@amounts=(10,24,39);
6@parts=('computer','rat',"kbd");
7
8$a=1;$b=2;$c='3';
9@count=($a,$b,$c);
10
11@empty=();
12
13@spare=@parts;
14
15print'@amounts=';
16print"@amounts ";
17
18print'@parts=';
19print"@parts ";
20
21print'@count=';
22print"@count ";
23
24print'@empty=';
25print"@empty ";
26
27print'@spare=';
28print"@spare ";
29
30
31#
32#Accessingindividualitemsinanarray
33#
34print'$amounts[0]=';
35print"$amounts[0] ";
36print'$amounts[1]=';
37print"$amounts[1] ";
38print'$amounts[2]=';
39print"$amounts[2] ";
40print'$amounts[3]=';
41print"$amounts[3] ";
42
43print"Itemsin@amounts=$#amounts ";
44$size=@amounts;print"SizeofAmount=$size ";
45print"Item0in@amounts=$amounts[$[] ";
以下是显示结果:
@amounts=102439
@parts=computerratkbd
@count=123
@empty=
@spare=computerratkbd
$amounts[0]=10
$amounts[1]=24
$amounts[2]=39
$amounts[3]=
Itemsin@amounts=2
SizeofAmount=3
Item
第5行,三个整数值赋给了数组@amounts。第6行,三个字符串赋给了数组@parts。第8行,字符串和数字分别赋给了三个变量,然后将三 个变量赋给了数组@count。11行创建了一个空数组。13行将数组@spare赋给了数组@parts。15到28行输出了显示的前5行。34到41 行分别存取数组@amounts的每个元素。注意$amount[3]不存在,所以显示一个空项。43行中使用$#array方式显示一个数组的最后一个 下标,所以数组@amounts的大小是($#amounts+1)。44行中将一个数组赋给了一个标量,则将数组的大小赋给了标量。45行使用了一个 Perl中的特殊变量$[,用来表示一个数组的起始位置(缺省为0)。
相关数组
一般的数组允许我们通过数字下标存取其中的元素。例如数组@food的第一个元素是$food[0],第二个元素是$food[1],以此类推。 但 Perl允许创建相关数组,这样我们可以通过字符串存取数组。其实,一个相关数组中每个下标索引对应两个条目,第一个条目叫做关键字,第二个条目叫做数 值。这样,你就可以通过关键字来读取数值。相关数组名以百分号(%)开头,通过花括号({})引用条目。例如:
%ages=("MichaelCaine",39,
"DirtyDen",34,
"Angie",27,
"Willy","21indogyears",
"TheQueenMother",108);
这样我们可以通过下面的方法读取数组的值:
$ages{"MichaelCaine"};#Returns39
$ages{"DirtyDen"};#Returns34
$ages{"Angie"};#Returns27
$ages{"Willy"};#Returns"21indogyears"
$ages{"TheQueenMother"};#Returns108
[目录]
--------------------------------------------------------------------------------
文件操作
文件句柄和文件操作
我们可以通过下面的程序了解一下文件句柄的基本用法。此程序的执行结果和UNIX系统
的cat命令一样:
#!/usr/local/bin/perl
#
#Programtoopenthepasswordfile,readitin,
#printit,andcloseitagain.
$file='/etc/passwd';#Namethefile
open(INFO,$file);#Openthefile
@lines=<info></info>;#Readitintoanarray
close(INFO);#Closethefile
print@lines;#Printthearray
open函数打开一个文件以供读取,其中第一个参数是文件句柄(filehandle)。文件句柄用来供Perl在以后指向该文件。第二个参数指向该文件的文件名。close函数关闭该文件。
open函数还可以用来打开文件以供写入和追加,只须分别在文件名之前加上>和>>:
open(INFO,$file);#Openforinput
open(INFO,">$file");#Openforoutput
open(INFO,">>$file");#Openforappending
open(INFO,"<$file");#Alsoopenforinput
另外,如果你希望输出内容到一个已经打开供写入的文件中,你可以使用带有额外参数的print语句。例如:
printINFO"Thislinegoestothefile. ";
最后,可以使用如下的语句打开标准输入(通常为键盘)和标准输出(通常为显示器):
open(INFO,'-');#Openstandardinput
open(INFO,'>-');#Openstandardoutput
一个Perl程序在它一启动时就已经有了三个文件句柄:STDIN(标准输入设备),STDOUT(标准输出设备)和STDERR(标准错误信息输出设备)。如果想要从一个已经打开的文件句柄中读取信息,可以使用<>运算符。
使用read和write函数可以读写一个二进制的文件。其用法如下:
read(HANDLE,$buffer,$length[,$offset]);
此命令可以把文件句柄是HANDLE的文件从文件开始位移$offset处,共$length字节,读到$buffer中。其中$offset是 可选项,如果省略$offset,则read()从当前位置的前$length个字节读取到当前位置。可以使用下面的命令查看是否到了文件末尾:
eof(HANDLE);
如果返回一个非零值,则说明已经到达文件的末尾。
打开文件时可能出错,所以可以使用die()显示出错信息。下面打开一个叫做“test.data”的文件:
open(TESTFILE,"test.data")||die" $0Cannotopen$! ";
[目录]
--------------------------------------------------------------------------------
流程控制
foreach循环
在Perl中,可以使用foreach循环来读取数组或其他类似列表结构中的每一行。请看下面的例子:
foreach$morsel(@food)#Visiteachiteminturn
#andcallit$morsel
{
print"$morsel ";#Printtheitem
print"Yumyum ";#Thatwasnice
}
每次要执行的命令用花括号括出。第一次执行时$morsel被赋予数组@food的第一个元素的值,第二次执行时$morsel被赋予数组@food的第二个元素的值,以此类推直到数组的最后一个元素。
判断运算
在Perl中任何非零的数字和非空的字符串都被认为是真。零、全为零的字符串和空字符串都为假。
下面是一些判断运算符:
$a==$b如果$a和$b相等,则返回真。
$a!=$b如果$a和$b不相等,则返回真。
$aeq$b如果字符串$a和字符串$b相同,则返回真
$ane$b如果字符串$a和字符串$b不相同,则返回真。
你可以使用逻辑运算符:
($a&&$b)$a与$b。
($a||$b)$a或$b。
!($a)非$a。
for循环
Perl中的for结构和C语言中的for结构基本一样:
for(initialise;test;inc){
first_action;
second_action;
etc
}
下面是一个for循环的例子,用来显示从0到9的数字:
for($i=0;$i<10;++$i)#Startwith$i=1
#Doitwhile$i<10
#Increment$ibeforerepeating
{
print"$i ";
}
while和until循环
下面是一个while和until循环的例子。它从键盘读取输入直到得到正确的口令为止。
#!/usr/local/bin/perl
print"Password?";#Askforinput
$a=<stdin></stdin>;#Getinput
chop$a;#Removethenewlineatend
while($ane"fred")#Whileinputiswrong...
{
print"sorry.Again?";#Askagain
$a=<stdin></stdin>;#Getinputagain
chop$a;#Chopoffnewlineagain
}
当输入和口令不相等时,执行while循环。
你也可以在执行体的末尾处使用while和until,这时需要用do语句:
#!/usr/local/bin/perl
do
{
"Password?";#Askforinput
$a=<stdin></stdin>;#Getinput
chop$a;#Chopoffnewline
}
while($ane"fred")#Redowhilewronginput
条件结构
Perl也允许if/then/else表达式。请看下面的例子:
if($a){
print"Thestringisnotempty ";
}
else{
print"Thestringisempty ";
}
注意在Perl中,空字符被认为是假。
If结构中也可以使用嵌套结构:
if(!$a)#The!isthenotoperator
{
print"Thestringisempty ";
}
elsif(length($a)==1)#Ifabovefails,trythis
{
print"Thestringhasonecharacter ";
}
elsif(length($a)==2)#Ifthatfails,trythis
{
print"Thestringhastwocharacters ";
}
else#Now,everythinghasfailed
{
print"Thestringhaslotsofcharacters ";
[目录]
--------------------------------------------------------------------------------
字符匹配
Perl字符匹配功能十分强大。字符匹配功能的核心是规则表达式(RE),也就是字符匹配过程中涉及到的格式。=~运算符用来进行格式匹配和替换。例如:
如果:
$s='Oneifbylandandtwoifbysea';
则:
if($s=~/ifbyla/){print"YES"}
else{print"NO"}
将会显示YES,因为ifbyla在字符串$s中。再例如:
if($s=~/one/){print"YES"}
else{print"NO"}
将显示NO,因为RE是对大小写敏感的。如果使用i选项,则将忽略大小写,则下面会显示出YES:
if($s=~/one/i){print"YES"}
else{print"NO"}
下面列出了RE中许多具有特殊意义的字符:
.任何字符除了换行符()
^一行和一个字符串的开始
$一行和一个字符串的结束
*其前一个字符重复零次或多次
+其前一个字符重复一次或多次
?其前一个字符重复零次或一次
例如:
if($x=~/l.mp/){print"YES"}
对于$x=“lamp”、“lump”、“slumped”将显示YES,但对于$x=“lmp”或“lessamperes”将不会显示YES。
再看下面的例子:
/fr.*nd/匹配frnd、friend、frontandback。
/fr.+nd/匹配frond、friend、frontandback。但不匹配frnd。
/10*1/匹配11、101、1001、100000001。
/b(an)*a/匹配ba、bana、banana、banananana。
/flo?at/匹配flat和float,但不匹配flooat。
方括号用来匹配其中的任何字符。方括号中的-符号用来表明
end