`

OS + Linux Shell bash / sh / ksh / csh / tcsh / adb shell

    博客分类:
  • OS
 
阅读更多

s

Android adb shell / ADB: Android debug bridge. 

Android手机实际是基于Linux系统的。

Google提供的ADB工具包带有fastboot.exe.rar

http://dl.iteye.com/topics/download/4f68ea40-5928-35ef-820c-f75956e3f26d

 

在你的android手机的设置中,Settings->Applications->Development->USB debugging勾选上,就可以允许PC通过adb shell命令远程登录你手机的linux系统

【安卓手机通用】android adb shell 命令大全

http://jingyan.baidu.com/article/8cdccae9955c4c315413cda8.html

【安卓通用】android adb shell 命令大全

http://jingyan.baidu.com/article/fb48e8be4f58216e622e14b5.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. 从电脑上发送文件到设备

*adb push <本地路径> <远程路径>

用push命令可以把本机电脑上的文件或者文件夹复制到设备(手机)

6. 从设备上下载文件到电脑

*adb pull <远程路径> <本地路径>

用pull命令可以把设备(手机)上的文件或者文件夹复制到本机电脑

adb push 和 adb pull命令使用教程

http://jingyan.baidu.com/article/67508eb43ea6859cca1ce4af.html

adb push命令 :从电脑上传送文件到手机;

adb pull命令 :从手机传送文件到电脑上;

获取大可乐手机 log 日志到当前目录,命令如下 :

adb pull /dev/log/main ./  

你在运行adb push这条命令时,可能会遇到failed to copy 'D:\file.xtxt' to '/system/' : Read-only file system 的报错信息,这是由于你没执行adb remount命令或者执行这条命令没成功; 

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注释符号 >>># 或 !

 

 
man
 

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基础知识

http://sucre.iteye.com/blog/639952

以下这些知识是在编写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 和 $(( )) 直接进行计算

 

命令的輸出在同一行  Linux 不换行输出
http://www.unix.com/zh-TW/unix-dummies-questions-answers/5720-command-output-one-line.html#ixzz0loLTak9x
 

分享平时工作中那些给力的shell命令

http://zhengdl126.iteye.com/blog/834464

http://yunhaozou.org/perl-shell/162.html

1.显示消耗内存/CPU最多的10个进程
ps aux | sort -nk +4 | tail
ps aux | sort -nk +3 | tail
—————————————————————————————————————————————————————
2.查看Apache的并发请求数及其TCP连接状态
#netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
 
LAST_ACK 1
SYN_RECV 1
ESTABLISHED 9
FIN_WAIT1 4
TIME_WAIT 127
 
 
其中的SYN_RECV表示正在等待处理的请求数;ESTABLISHED表示正常数据传输状态;TIME_WAIT表示处理完毕,等待超时结束的请求数。

关于TCP状态的变迁,可以从下图形象地看出:

状态:描述

CLOSED:无连接是活动的或正在进行

LISTEN:服务器在等待进入呼叫

SYN_RECV:一个连接请求已经到达,等待确认

SYN_SENT:应用已经开始,打开一个连接

ESTABLISHED:正常数据传输状态

FIN_WAIT1:应用说它已经完成

FIN_WAIT2:另一边已同意释放

ITMED_WAIT:等待所有分组死掉

CLOSING:两边同时尝试关闭

TIME_WAIT:另一边已初始化一个释放

LAST_ACK:等待所有分组死掉
 
—————————————————————————————————————————————————————
3.找出自己最常用的10条命令及使用次数(或求访问最多的ip数)
sed -e 's/| /\n/g' ~/.bash_history |cut -d ' ' -f 1 | sort | uniq -c | sort -nr | head
—————————————————————————————————————————————————————
4.日志中第10个字段表示连接时间,求平均连接时间
cat access_log |grep "connect cbp" |awk 'BEGIN{sum=0;count=0;}{sum+=$10;count++;}END{printf(“sum=%d,count=%d,avg=%f\n”,sum,count,
sum/count)}'
—————————————————————————————————————————————————————
5.lsof命令
lsof abc.txt 显示开启文件abc.txt的进程
lsof -i :22 知道22端口现在运行什么程序
lsof -c abc 显示abc进程现在打开的文件
lsof -p 12  看进程号为12的进程打开了哪些文件
—————————————————————————————————————————————————————
6.杀掉一个程序的所有进程
pkill -9 httpd
killall -9 httpd
注意尽量不用-9,数据库服务器上更不能轻易用kill,否则造成重要数据丢失后果将不堪设想。
—————————————————————————————————————————————————————
7.rsync命令(要求只同步某天的压缩文件,而且远程目录保持与本地目录一致)
/usr/bin/rsync -azvR –password-file=/etc/rsync.secrets `find . -name "*$yesterday.gz"  -type f ` storage@192.168.2.23::logbackup/13.21/
—————————————————————————————————————————————————————
8.把目录下*.sh文件改名为*.SH
find .  -name "*.sh” | sed  's/\(.*\)\.sh/mv \0 \1.SH/' |sh
find .  -name "*.sh” | sed  's/\(.*\)\.sh/mv & \1.SH/' |sh  (跟上面那个效果一样)
—————————————————————————————————————————————————————
9.ssh执行远程的程序,并在本地显示
ssh -n -l zouyunhao 192.168.2.14 “ls -al /home/zouyunhao”
—————————————————————————————————————————————————————
10. 直接用命令行修改密码
echo "zouyunhaoPassword" |passwd –stdin zouyunhao
—————————————————————————————————————————————————————
11. ssh免密码登录
ssh-keygen
ssh-copy-id -i ~/.ssh/id_rsa.pub user@remoteServer
—————————————————————————————————————————————————————
12.以http方式共享当前文件夹的文件
$ python -m SimpleHTTPServer
在浏览器访问http://IP:8000/即可下载当前目录的文件。
—————————————————————————————————————————————————————
13.shell段注释
:<<'echo hello,world!'
—————————————————————————————————————————————————————
14.查看服务器序列号
dmidecode |grep "Serial Number"   (查看机器其他硬件信息也可用这个命令)
—————————————————————————————————————————————————————
15.查看网卡是否有网线物理连接
/sbin/mii-tool
 
Redhat新建用户如yhpre指定特定操作界面方法如下
 ------------------------------------------------------------------
  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] >
 
[root@b2cpreweb2 ~]#more  /home/yhpre/.bash_profile
# 添加如下内容
export PATH
sudo ./menu.sh
[root@b2cpreweb2 ~]#more /home/yhpre/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

 
 
bash 详解
http://laozy.iteye.com/blog/391311
最简单的例子 —— Hello World! 
几乎所有的讲解编程的书给读者的第一个例子都是 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 

这个结构请大家自己编写一个例子来验证。
test.sh   shell 循环
# /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"); 

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

 

end

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics