Shell编程常识
时间:2006-02-19 来源:cnscn2008
一、用户登陆进入系统后的系统环境变量:
$HOME 使用者自己的目录
$PATH 执行命令时所搜寻的目录
$TZ 时区
$MAILCHECK 每隔多少秒检查是否有新的信件
$PS1 在命令列时的提示号
$PS2 当命令尚未打完时,Shell 要求再输入时的提示号
$MANPATH man 指令的搜寻路径
二、特殊变量:
$0 这个程序的执行名字
$n 这个程序的第n个参数值,n=1..9
$* 这个程序的所有参数
$# 这个程序的参数个数
$$ 这个程序的PID
$! 执行上一个指令的PID
$? 执行上一个指令的返回值
三、shell中的变元:
* 任意字符串
? 一个任意字符
[abc] a, b, c三者中之一
[a-n] 从a到n的任一字符
四、几个特殊字符表示
\b 退回
\c 打印一行时没有换行符 这个我们经常会用到
\f 换页
\r 回车
\t 制表
\v 垂直制表
\\ 反斜线本身
五、判断文件的属性
格式:-操作符 filename
-e 文件存在返回1, 否则返回0
-r 文件可读返回1,否则返回0
-w 文件可写返回1,否则返回0
-x 文件可执行返回1,否则返回0
-o 文件属于用户本人返回1, 否则返回0
-z 文件长度为0返回1, 否则返回0.
-f 文件为普通文件返回1, 否则返回0
-d 文件为目录文件时返回1, 否则返回0
六、测试字符串
字符串1 = 字符串2 当两个字串相等时为真
字符串1 != 字符串2 当两个字串不等时为真
-n 字符串 当字符串的长度大于0时为真
-z 字符串 当字符串的长度为0时为真
字符串 当串字符串为非空时为真
七、测试两个整数关系
数字1 -eq 数字2 两数相等为真
数字1 -ne 数字2 两数不等为真
数字1 -gt 数字2 数字1大于数字2为真
数字1 -ge 数字2 数字1大于等于数字2为真
数字1 -lt 数字2 数字1小于数字2为真
数字1 -le 数字2 数字1小于等于数字2为真
八、逻辑测试
-a 与
-o 或
! 非
今天介绍shell特殊字符的引用
===============================
shell中的特殊字符有
1、$ 美元符
2、\ 反斜杠
3、` 反引号
4、" 双引号
5、< ,>,*,?,[,]
下面我一一举列说明
一、$符号
1、echo $? 显示的是上一条指令退出状态
2、echo "$?" 效果同上
3、echo '$?' 显示的是$?
4、echo \$? 显示的是$?
5、echo "\$?" 显示的是$?
大家可能已经看出 $符号在双引号中具有特殊意义 双引号对$符号不起作用
而单引号可以将特殊字符的的特殊意义屏蔽掉,使其能显示为字符本身,反斜
杠也可以将特殊字符的特殊含义屏蔽掉,使特殊字符失去特殊含义。
二、\ 反斜杠
反斜杠的作用是将特殊符号字符的特殊含义屏蔽掉,使其还是原字符
A=1234
echo \$A 显示为$A 如果不加\将显示为1234
echo \` 显示为`
echo \" 显示为双引号
echo \\ 显示为\
三、` 反引号
反引号的功能是命令替换,将反引号中的字符串做为命令来执行,我们在用shell编程时经常用的到 将系统命令的执行结果赋给一个变量
A=`date`
echo $A 显示的不是date而是当时的时间串
比如有一文件A的内容如下
ABCDEFG
1234456
abcdefg
B=`cat A|grep 234`? # 检索文件A中含有字符串234的行
echo $B 将显示为1234456
echo "$B" 将显示为什么?
echo "\$B" 将显示为什么?读者自己试试
四、" 双引号
在系统中有些特殊字符,为避免引用这些特殊字符 往往用双引号或单引号将这些特殊字符引起来,使其不具有特殊含义。
但有一部分特殊字符在引号中还是具有特殊含义,用双引号引起来是不起作用的。本文中所列的前四个特殊字符在双引号中还是特殊字符。为了使其不具有特殊含义一是用单引号引进来二是用\反斜线使其失去作用。
比如我们想原样输出这些特殊字符
echo """
echo "$"
echo "\"
echo "`"
以上不是你所期望的结果,因为双引号对它们不起作用,你只能这样才能输出这些特殊字符的原形
echo '"'
echo '$'
echo '\'
echo '`'
或
echo "\""
echo "\$"
echo "\\"
echo "\`"
将分别显示为 " $ \ `
五、其它特殊字符
大家注意到 除了前四个特殊字符外 我将其它的特殊字符都放在一块,这是因为前四个特殊字符在双引号中还是具有特殊含义,所以单独拿出来讲,除此以外的特殊字符如果你要输出这些特殊字符的原形,你就可以用双引号或单引号引起来使其失去特殊含义。
< ,>,*,?,[,]对shell有特殊含义 但你可以用双引号引起来输入这些原形
讲了这么多大家是不是已经注意到所有的特殊字符在单引号中失去特殊含义,如果你要输出特殊字符原形但又记不清那些特殊字符在双引号中不能输出原形,建议你干脆用单引号引起来。
今天介绍条件测试语句
一、if 条件语句
格式:
if 条件表达式
then #当条件为真时执行以下语句
命令列表
else #为假时执行以下语句
命令列表
fi
if 语句也可以嵌套使用
if 条件表达式1
then
if 条件表达式2
then
命令列表
else
if 条件表达式3
then
命令列表
else
命令列表
fi
fi
else
命令列表
fi
你可以进行多层嵌套 一个if语句一定要跟一个fi 表示该层条件结束 否则会造成语法错误
结合前面讲的 举例如下:
这里先讲一个条件语句中用到的命令test 表示测试test后面的条件是否为真
if test -f "$1"
then
lpr $1
else
if test -d "$1"
then
cd $1
lpr $1
else
echo "$1不是文件或目录"
fi
fi
以上的例子还可以改成如下所示
if test -f "$1"
then
lpr $1
elif test -d "$1" #elif 同else if
then
(cd $1;lpr $1)
else
echo "$1不是文件或目录"
fi??????
以上的例子不知您是否看懂是什么意思吗?
假如我们现在将这个例子保存为prfile
chmod +x prfile
执行刚才的程序
./prfile aaa
这个例子是检查你的输入的参数是否是一个文件 如果是就打印 如果是一个目录 先转目录再打印 如果即不是文件也不是目录给出提示
二、多重条件测试语句case
格式:
case 字串 in
模式) 命令列表;;
模式) 命令列表;;
....
esac
多重条件语句是以case 开始以esac结束 中间可以有多个条件列表 功能是测试字串和和里面的模式有没有匹配的,有就执行里面的命令列表 模式也可以是*号 表示任意字串,每个模式里面的最后要心;;双引号结束,否则会发生语法错误。
现举例如下:
case $1 in
*.c)
cc $1
;;
*.txt)
lpr $1
;;
*)
echo "未知的类型"
esac
假如将以上内容保存在文件abc中
chmod +x abc
执行 ./abc a.c 将会对文件a.c进行编译
执行 ./abc readme.txt 将会把文件通过打印机
假如我将以上内容改一下,你是否会知道它的执行结果?
case $1 in
*)
cc $1
;;
*.txt)
lpr $1
;;
*.c)
echo "未知的类型"
esac
今天介绍循环语句
一. while 循环
while 命令格式
while 条件表
do
命令表
done
执行过程
shell首先执行条件表,如果条件表的最后一条语句的退出状态为零,则执行盾环体内的命令
表,执行完后,再检查条件表,如果退出状态为零将继续执行,如此循环往复直到条件表的
最后一条语句的退出状态非零. 退出状态为零就是条件为真True.
举例说明 假如shell文件的内容如下:
Sum=0
i=0
while true #true是系统的关键词 表示真
do
i=`expr $i + 1`
Sum=`expr $Sum + $i`
if [ $i = "100" ]
then
break;
fi
done
echo $i $Sum
最后这个程序显示的是 100 5050
这个程序的运算就是将1到100加起来
下面将这个程序再改动一下
Sum=0
i=0
while [ $i != "100" ]
do
i=`expr $i + 1`
Sum=`expr $Sum + $i`
done
echo $i $Sum
改动后的程序运算结果和上面是一样 但程序比上面的要简练
在这个循环中还可以以until做为测试条件 它正好与while测试的条件相反,也就是当条件为假时将继续执行循环体内的语句,否则就退出循环体,下面还用这个例子.
Sum=0
i=0
until [ $i = "100" ]
do
i=`expr $i + 1`
Sum=`expr $Sum + $i`
done
echo $i $Sum
当i不等于100时循环 就是当条件为假时循环,否则就退出,而第一个例子是当i不等于100
时循环,也就是测试条件为真时循环.
二.for 循环
命令格式:
for 变量 in 名字列表
do
命令列表
done
这里的名字列表是一个由空格分隔的字符串列表,shell在执行for循环时每次依次从名字表
中取出一个字符串赋给循环变量作为变量的值.
在写for语句时,也可以省略in 名字列表部分,这表示用当前的位置参数来代替这时的名
字列表.
下面举个例子
比如在你的电脑中有两个目录,一个是aa,一个是bb在这两个目录中有5个相同的文件,但其
中一个目录中的一个或多个文件刚刚修改过,现在我忘记刚才改的是那几个文件 了,那么我靠梢员冉弦幌抡饬礁瞿柯嫉奈募?椭?懒?程序如下:
for File in a1 a2 a3 a4 a5
do
diff aa/$File bb/$File
done
下面再举一个不带名字列表的例子
for File
do
echo $Filw
done
文件内容保存在a.sh中 并可执行
我们在执行这个shell程序时命令行如下:
a.sh a1 a2 a3 a4 a5
执行结果如下:
a1
a2
a3
a4
a5
大家从这个例子中可以看到命令行的参数被逐一读入一次
三.循环控制语句
break 命令不执行当前循环体内break下面的语句从当前循环退出.
continue 命令是程序在本循体内忽略下面的语句,从循环头开始执行.
一,命令组合:圆括号和花括号
shell中有两种方法将命令组合在一起:圆括号和花括号.圆括号使shell创建一个子shell
来读取并执行括起来的名命令.左括号和右括号不论出现在命令行中的什么位置,shell都会
认为它们具有特殊的组合意义的.只有用双引号将它们括起来引用,才表示圆括号或花括号
的原义.例如:
echo a(b)
将出现语法上的错误,要想输出a(b)字符串 只能括起来
echo "a(b)"
或echo a"("b")"
这样才能被shell正确解释.
利用组合命令有什么作用呢?
一,用圆括号组合命令
圆括号的组合命令可以创建子进程运行组合程序,建立子进程的功能是很有用的,因为
子shell在组合命令中的种种操作都不会影响到当前shell的各变量的值.
例如:
子进程在执行组合命令时改变了工作目录,并在新的工作目录下执行一系例命令,执行
完后它可以不必返回原工作目录,因为子进程工作目录的改变不会影响到当前工作目录.
创建子进程后将当前的环境也同样传给子shell,当前shell中用export输出到环境中的
各变量在子shell中同样有效.
花括号也可以将命令组合在一起.左 右花括号只有作为一条命令的第一个字出现时,
shell才它们含有特殊含义.
与圆括号不同的是花括号并不创建子shell,只是由当前的shell来读取并执行括起来的
命令.有时用户希望使用一组命令的顺序输出作为另一组命令的输入,此时用花括号是很方
便的.
不论是用圆括号不是花括号,退出状态都是等于最后一条括起来的命令的退出状态.
二,可以在当前shell中执行的命令
用户在使用shell时一定要了解那些是可以在当前shell中执行的命令 那些不可以
可以在当前shell中执行的命令有:
break case cd continue
echo eval exec exit
export for if read
readonly return set shift
test times trap umask
until wait while
: {}
[来源]http://www.7880.com/Info/Article-6b453e20.html
=============================================================
.chmod
chmod [who] operator [permission] filename
who
u 所有者
g 组
o 其他用户
a 所有用户
operator
+ 增加权限
- 取消权限
= 设定权限
permission
r 读权限
w 写权限
x 执行权限
s 文件属主和组set-ID
l 给文件加锁,使其他用户无法访问
t 粘性位 (如果一个目录上出现粘着位, 这就意味着目录中的文件只有其属主才可以删除,即使某个同组用户具有和属主同等的权限。不过有的系统上,这个规则并不严格; 如果在文件列表时看到t, 则意味着脚本或程序在执行时会被放在交换区(虚存),不过由于当今的内存价格如此这低,大可不必理会文件的t应用)
示例:
chmod a+x file
chmod og-w file
chmod g+w file
chmod u+x file
chmod go+x file
.suid/guid
chmod u+s file
# ls -l a.html
-rw-r--r-- a.html
# chmod u+s a.html
# ls -l a.html
-rwSr--r-- a.html
.find
find path -options [-print -exec -ok]
-exec find命令将匹配的文件执行exec所给出的shell命令 -exec cmd {} \; (注意: {} 和 \;间的空格)
-ok 同-exec只不过要求对命令的执行进行确认
-name 匹配文件名
find . -name "*.txt" -print
find . -name "[a-z]*" -print
find . -name * -print 或 find . -print
find . -name "[a-z][a-z][0--9][0--9].txt" -print
-perm 匹配权限
find . -perm 755 -print
find . -perm -007 -print
-prune 忽略目录 (如果使用了-depth选项,则忽略-prune选项) [没有试用成功]
find /apps -name "/apps/bin" -prune -o -print
-user 匹配用户
find . -user cnscn -print
-nouser 帐户属主已被删除的文件
find . -nouser -print
-group
-nogroup
-mtime +-n 按更改时间查找文件
find . -mtime -5 -print 查找5日内更改过的文件
find . -mtime +5 -print 查找5日前更改过的文件
-newer file 查找比file更改时间新的文件
! -newerfile2 查找比file更改时间旧的文件
find . -newer a.txt
find . ! -newer a.txt
# date
2006年 09月 13日 星期三 11:16:07 CST
# touch -t 0609120000 a.txt 创建文件a.txt并指定它的更改时间
# ls -l a.txt
-rw-r--r-- 1 root root 0 09-12 00:00 a.txt
-type
f
b
d
c
p
l
-maxdepth 指定递归操作的最在目录深度
# find . -maxdepth 1 -type d
.
./tmp
./mrtg-2.14.5
./piano
./tidy4aug00
-mount 仅在当前的文件系统内进行操作
-fstype
-cpio 将查询结果进行cpio命令进行操作
find etc home apps -depth -print | cpio -ivcdC65536 -o /dev/rmt0
-exec cmd {} \;
-ok cmd {} \;
find . -type f -exec ls -l {} \;
find . -type f -exec rm -f {} \;
find . -type f -ok ls -l {} \;
find . -type f -ok rm -f {} \;
-size n[c]
-depth
-follow
.xargs
功能类似 -exec , 但和-exec不同的是 它一次只是取得部分find查询到的文件结果, 而-exec是一次性获取全部文件结果,容易导致参数太多
# find . -type f -name "*.mp3" -print | xargs ls -l
-rw-r--r-- 1 root root 3985349 09-07 16:05 ./piano/025.mp3
-rw-r--r-- 1 root root 3936256 09-07 16:06 ./piano/duni.mp3
-rw-r--r-- 1 root root 28 09-07 16:23 ./piano/丝丝记忆.mp3
-rw-r--r-- 1 root root 2423745 09-07 16:24 ./piano/异国情.mp3
-rw-r--r-- 1 root root 2967512 09-07 16:20 ./piano/思乡曲.mp3
-rw-r--r-- 1 root root 4567040 09-07 16:20 ./piano/星空.mp3
.echo
echo -n "string..." 不换行输出
echo -e "string...\c" 同上
.read variable1 variable2 从标准输入读内容到变量
# read name
sssssssssss
# echo $name
sssssssssss
.文件重定向
cmd > file 结果输出到文件file
cmd >> file 结果附加到文件file
cmd 1> file 结果输出到文件file
cmd 2> file 标准错误输出到文件file
cmd > file 2>&1 结果和标准错误输出到文件file
cmd < file1 > file2 命令以file1为输入, 然后以file2为输出
cmd <<delimiter 从标准输入中读入, 直到遇到delimiter分界符
cat >>file <<HERE 把HERE间的内容发送给文件file, 不要忘记>>
>ssssssss
>ssaaaaaaa
>HERE
cmd <&m 把文件描述符m作为标准输入
cmd >&m 把标准输出重定向到文件描述符m中
cmd <&_ 关闭标准输入
.&&
cmd1 && cmd2 顺序执行命令cmd1和cmd2 (只有cmd1执行成功才会执行cmd2)
.||
cmd1 && cmd2 选择执行cmd1和cmd2(如果cmd1执行失败,则执行cmd2)
awk '{print $1,$2}' acc.qtr >qtr.tmp || echo "Error" #如果前面执行错误,则报告错误
.() 一般很少单独执行而是和&& || 组合运行
(cmd1;cmd2;cmd3...) 在当前shell中执行一组命令
mail ... || (echo "Error" | mail; exit)
.{} 一般很少单独执行而是和&& || 组合运行
{cmd1;cmd2;cmd3...} 在子shell中执行一组命令
.正则表达式
^ 匹配行首
$ 匹配行尾
* 匹配0个或多个前面的单个字符
[] 匹配[]内的任意一个字符
\ 转义
pattern\{n\} 匹配n次pattern
pattern\{n,\} 匹配最少n次pattern
pattern\{n,m\} 匹配n到m次pattern
经常使用的正则表达式
^
$
^[the]
[Ss]igna[lL]
[mayMAY]
^User$
[tty]$ 以tty结尾的行
\.
^d..x..x..x
^[^l]
[.*0]
[000*] 000或更多个
[iI] i或I
[iI][nN] in或iN或In或IN
[^$] 空行
^......$ 含6个字符的行
[a-zA-Z] 任意单个字符
[a-z][a-z]* 到少一个小写字母
[^0-9\$] 非数字或$
[^0-0A-Za-z] 非数字或字母
[123] 1或2或3
[Dd]evice device或Device
De..ce 以De开始中间两个任意字符最后是ce
\^q 以^q开始的行
^.$ 只有一个字符的行
^\.[0-9][0-9] 一个句点和两个数字开始的行
'"Device"' Device
De[Vv]ice\. Device 或 device
[0-9]\{2\}-[0-9]\{2\}-[0-9]\{4\} dd-mm-yyyy
[0-9]\{3\}\.[0-9]\{3\}\.[0-9]\{3\}\.[0-9]\{3\} 匹配IP地址
[^.*$] 匹配任意行
.grep
-E 匹配正则表达式
grep -ERv "a|g" ./ 查询不含字符a与g的文件
.awk
域分隔符
awk -F":" '{print $1}' a.txt
awk -F: '{print $1}' a.txt
awk脚本
awk -f a.wak a.txt
BEGIN/END
awk 'BEGIN {print "Name Belt\n-------------------"} {print $1"\t"$4} END{print "END..." } ' a.txt
$n ~ /正则/
awk '$0 ~ /Brown' a.txt
awk '$0 !~ /Brown/' a.txt
条件
awk '$3=="48" {print $0}' a.txt
awk '{if($3~/48/) print $0}' a.txt
awk '{if($3!~/48/) print $0}' a.txt
awk '$4 != "Tom" {print $0}' a.txt
awk '{if($6 <= $7) print $0 }' a.txt
awk '/[Gg]reen/' a.txt
awk '$1~/^ ... a/' a.txt
awk '$0 ~ /(Ye|Br)/' a.txt
awk '/^48/' a.txt
awk '{if($1=="Y" && $2=="G") print $0}' a.txt
awk '{if($1=="Y" || $2=="G") print $0}' a.txt
内置参数
ARGC 参数个数
ARGV 参数数组
ENVIRON 支持队列中系统环境变量的使用
FILENAME awk浏览的文件名
FNR 浏览文件的记录数
NR 已读出的记录数
FS 设置输入域分隔符,等 价于命令行-F选项
NF 记录的域的个数
OFS 输出域分隔符
RS 控制记录分隔符
# awk -F"S" '{print ENVIRON["HOME"] }' a.txt
/root
awk '{name=$1; belts=$4; if(belts ~ /Y/) print name" is belt" }' a.txt
awk '(total+=$6); END{ print "Total:" total}' 打印每一行及END一行
awk '{(total+=$6)}; END{ print "Total:" total}' 只打印END一行
ls -l | awk '/^[^d]/ {print $9"\t"$5} {total+=$5} END{print "Total: KB:" total}'
gsub(r,s) 在$0中用s替代r
#awk -F"S" 'gsub(/a/,"xxxxxxxxx"){print $0 }' a.txt
Return-Pxxxxxxxxxth: <[email protected]>
by mx28.mxxxxxxxxxil.sohu.com (Postfix) with ESMTP id 747AD00442AD
gsub(r,s,str) 在str中用s替代r
# awk -F":" 'gsub(/a/,"xxxxxxxxx",$1){print $0 }' a.txt
Return-Pxxxxxxxxxth <[email protected]>
by mx28.mxxxxxxxxxil.sohu.com (Postfix) with ESMTP id 747AD00442AD
for <cnstest%[email protected]>; Mon, 11 Sep 2006 18 03 11 +0800 (CST)
index(s,t) 返回字符串s中t的第一次出现的位置
length(s) 返回串s的长度
match(s,r) 测试s是否包含匹配r的字符串
# awk 'BEGIN{print match("ANCD",/d/)}'
0
# awk 'BEGIN{print match("ANCD",/D/)}'
4
split(s,arr,fs) 在fs上把分成数组arr, 返回数组长度
# awk 'BEGIN{print split("12#33#44#555#66",tmparr,"#")": "; print tmparr[0]" "tmparr[1]" "tmparr[3]}'
5: 12 44
sprint(fmt,exp) 返回经fmt格式化过的exp
sub(r,s) 用$0中最左边最长的子串代替s
# awk -F":" 'sub(/a/,"xxxxxxxxx"){print $0 }' a.txt
Return-Pxxxxxxxxxth: <[email protected]>
by mx28.mxxxxxxxxxil.sohu.com (Postfix) with ESMTP id 747AD00442AD
for <cnstest%[email protected]>; Mon, 11 Sep 2006 18:03:11 +0800 (CST)
substr(s,p) 返回s中从p开始的后续部分
substr(s,p,n) 返回字符串s中从p开始长度为n的后续部分
printf “%s\n”,"sssssssss"
- 左对齐
width 宽度
.prec 小数点右边的位数
%f 浮点数
#awk 'BEGIN{printf "%f\n",999}'
999.000000
%c 字符
%d 整数
%e 科学记数法
%g awk决定使用哪种浮点数
%o 八进制
%s 字符串
%x 十六进制
向awk传递参数
# awk '{ print AGE}' AGE=777 a.txt
777
777
FS的用法
#cat a.awk
!/bin/awk -f
BEGIN{
FS=":"
}
{
print $1
}
数组
# awk 'BEGIN{arr["a"]="b"; arr["b"]="c"; for(key in arr) print arr[key] }'
b
c
=======================================
.sed 是一个非交互性文本流编辑器
.sed [选项] sed命令 File
sed [选项] -f sed脚本 File
选项:
-n 不输出结果
-c
-f
命令:
p 打印匹配行
= 显示行号
s 替换
r 从另一个文件中读取文本
w 写文本到一个文本
q 第一个模式匹配完成后退出或立即退出
l 显示与八进制ASCII代码等价的控制字符
{} 在定位行执行的命令组
g 将模式2粘贴到/pattern n/
y 传送字符
n 延续到下一输入行,允许跨行的模式匹配语句
数据行定位
x x为一行号,如1
x,y 从x,到y的行
/pattern/ 包含模式的行/abc/或/[a-z]
/pattern/pattern/ 同时包含两个模式的行/disk/disks/
pattern/,x 在给定行号上查询含模式的行/disk/,3
x,/pattern/ 通过行号和模式查询匹配行 3,/disk/
x,y! 查询不含指定行号x和y的行, 如 1,2!
#head a.txt
Return-Path: <[email protected]>
Delivered-To: [email protected]
.在每一行后加入一行
#sed 'absssssssssssssss' a.txt (此处a为添加一行的命令, bssssss... 为要添加的内容)
Return-Path: <[email protected]>
bsssssssssssssss
Delivered-To: [email protected]
bsssssssssssssss
#sed -n '2p' a.txt (显示第二行)
Delivered-To: [email protected]
#sed -n '2,4p' a.txt (显示第二行到第四行)
Delivered-To: [email protected]
Received: from sohumx180.sohu.com (unknown [192.168.132.180])
by mx28.mail.sohu.com (Postfix) with ESMTP id 747AD00442AD
#sed -n '/sohu/p' a.txt (显示含sohu的行)
Delivered-To: [email protected]
Received: from sohumx180.sohu.com (unknown [192.168.132.180])
#sed -n '1,$p' a.txt (显示整个文件)
#sed -n 'p' a.txt
#sed -n '/.*ohu/p' a.txt (任意字符)
Delivered-To: [email protected]
Received: from sohumx180.sohu.com (unknown [192.168.132.180])
by mx28.mail.sohu.com (Postfix) with ESMTP id 747AD00442AD
#sed -n '$p' a.txt (显示第2行)
Delivered-To: [email protected]
#sed -ne '/sohu/p' -e '/sohu/=' a.txt (显示文本及行号)
Delivered-To: [email protected]
2
Received: from sohumx180.sohu.com (unknown [192.168.132.180])
3
by mx28.mail.sohu.com (Postfix) with ESMTP id 747AD00442AD
4
.$cat a.sed (sed脚本)
#!/bin/sed -f
/sohu/ a\ 在含sohu的行后添加一行,内容为hello....
hello.....
执行脚本
#./a.sed a.txt
Return-Path: <[email protected]>
Delivered-To: [email protected]
hello.....
Received: from sohumx180.sohu.com (unknown [192.168.132.180])
hello.....
.$cat a.sed (sed脚本)
#!/bin/sed -f
/sohu/ i\ 在含sohu的行前添加一行,内容为hello....
hello.....
#./a.sed a.txt
Return-Path: <[email protected]>
hello.....
Delivered-To: [email protected]
hello.....
Received: from sohumx180.sohu.com (unknown [192.168.132.180])
.$cat a.sed (sed脚本)
#!/bin/sed -f
/sohu/ c\ 替换含sohu的行为行hello....
hello.....
# ./a.sed a.txt
Return-Path: <[email protected]>
hello.....
hello.....
hello.....
hello.....
.$cat a.sed (sed脚本)
#!/bin/sed -f
3 c\ 把第3行替换为hello....
hello.....
#./a.sed a.txt
Return-Path: <[email protected]>
Delivered-To: [email protected]
hello.....
#sed '1d' a.txt 删除第一行
Delivered-To: [email protected]
Received: from sohumx180.sohu.com (unknown [192.168.132.180])
#sed '1,2d' a.txt 删除第一到第2行
Received: from sohumx180.sohu.com (unknown [192.168.132.180])
by mx28.mail.sohu.com (Postfix) with ESMTP id 747AD00442AD
#sed 's/sohu/xxxxxxxx/g' a.txt 把sohu替换为xxxxxxxxxx
Return-Path: <[email protected]>
Delivered-To: [email protected]
#sed 's/sohu/xxxxxxxx/gw b.txt' a.txt 把sohu替换为xxxxxxxxxx, 并把替换的内容输出写到b.txt
Return-Path: <[email protected]>
Delivered-To: [email protected]
#cat b.txt
Delivered-To: [email protected]
Received: from xxxxxxxxmx180.sohu.com (unknown [192.168.132.180])
>-------by mx28.mail.xxxxxxxx.com (Postfix) with ESMTP id 747AD00442AD
>-------for <cnstest%[email protected]>; Mon, 11 Sep 2006 18:03:11 +0800 (CST)
>-------by xxxxxxxxmx180.sohu.com (Postfix) with SMTP id 7F69E05B70E1
>-------for <[email protected]>; Mon, 11 Sep 2006 18:03:10 +0800 (CST)
To: [email protected]
$sed '/sohu/r b.txt' a.txt 把b.txt的内容,附加到含有sohu的行的后面
#sed '/sohu/q' a.txt 第一次匹配后退出
Return-Path: <[email protected]>
Delivered-To: [email protected]
$HOME 使用者自己的目录
$PATH 执行命令时所搜寻的目录
$TZ 时区
$MAILCHECK 每隔多少秒检查是否有新的信件
$PS1 在命令列时的提示号
$PS2 当命令尚未打完时,Shell 要求再输入时的提示号
$MANPATH man 指令的搜寻路径
二、特殊变量:
$0 这个程序的执行名字
$n 这个程序的第n个参数值,n=1..9
$* 这个程序的所有参数
$# 这个程序的参数个数
$$ 这个程序的PID
$! 执行上一个指令的PID
$? 执行上一个指令的返回值
三、shell中的变元:
* 任意字符串
? 一个任意字符
[abc] a, b, c三者中之一
[a-n] 从a到n的任一字符
四、几个特殊字符表示
\b 退回
\c 打印一行时没有换行符 这个我们经常会用到
\f 换页
\r 回车
\t 制表
\v 垂直制表
\\ 反斜线本身
五、判断文件的属性
格式:-操作符 filename
-e 文件存在返回1, 否则返回0
-r 文件可读返回1,否则返回0
-w 文件可写返回1,否则返回0
-x 文件可执行返回1,否则返回0
-o 文件属于用户本人返回1, 否则返回0
-z 文件长度为0返回1, 否则返回0.
-f 文件为普通文件返回1, 否则返回0
-d 文件为目录文件时返回1, 否则返回0
六、测试字符串
字符串1 = 字符串2 当两个字串相等时为真
字符串1 != 字符串2 当两个字串不等时为真
-n 字符串 当字符串的长度大于0时为真
-z 字符串 当字符串的长度为0时为真
字符串 当串字符串为非空时为真
七、测试两个整数关系
数字1 -eq 数字2 两数相等为真
数字1 -ne 数字2 两数不等为真
数字1 -gt 数字2 数字1大于数字2为真
数字1 -ge 数字2 数字1大于等于数字2为真
数字1 -lt 数字2 数字1小于数字2为真
数字1 -le 数字2 数字1小于等于数字2为真
八、逻辑测试
-a 与
-o 或
! 非
今天介绍shell特殊字符的引用
===============================
shell中的特殊字符有
1、$ 美元符
2、\ 反斜杠
3、` 反引号
4、" 双引号
5、< ,>,*,?,[,]
下面我一一举列说明
一、$符号
1、echo $? 显示的是上一条指令退出状态
2、echo "$?" 效果同上
3、echo '$?' 显示的是$?
4、echo \$? 显示的是$?
5、echo "\$?" 显示的是$?
大家可能已经看出 $符号在双引号中具有特殊意义 双引号对$符号不起作用
而单引号可以将特殊字符的的特殊意义屏蔽掉,使其能显示为字符本身,反斜
杠也可以将特殊字符的特殊含义屏蔽掉,使特殊字符失去特殊含义。
二、\ 反斜杠
反斜杠的作用是将特殊符号字符的特殊含义屏蔽掉,使其还是原字符
A=1234
echo \$A 显示为$A 如果不加\将显示为1234
echo \` 显示为`
echo \" 显示为双引号
echo \\ 显示为\
三、` 反引号
反引号的功能是命令替换,将反引号中的字符串做为命令来执行,我们在用shell编程时经常用的到 将系统命令的执行结果赋给一个变量
A=`date`
echo $A 显示的不是date而是当时的时间串
比如有一文件A的内容如下
ABCDEFG
1234456
abcdefg
B=`cat A|grep 234`? # 检索文件A中含有字符串234的行
echo $B 将显示为1234456
echo "$B" 将显示为什么?
echo "\$B" 将显示为什么?读者自己试试
四、" 双引号
在系统中有些特殊字符,为避免引用这些特殊字符 往往用双引号或单引号将这些特殊字符引起来,使其不具有特殊含义。
但有一部分特殊字符在引号中还是具有特殊含义,用双引号引起来是不起作用的。本文中所列的前四个特殊字符在双引号中还是特殊字符。为了使其不具有特殊含义一是用单引号引进来二是用\反斜线使其失去作用。
比如我们想原样输出这些特殊字符
echo """
echo "$"
echo "\"
echo "`"
以上不是你所期望的结果,因为双引号对它们不起作用,你只能这样才能输出这些特殊字符的原形
echo '"'
echo '$'
echo '\'
echo '`'
或
echo "\""
echo "\$"
echo "\\"
echo "\`"
将分别显示为 " $ \ `
五、其它特殊字符
大家注意到 除了前四个特殊字符外 我将其它的特殊字符都放在一块,这是因为前四个特殊字符在双引号中还是具有特殊含义,所以单独拿出来讲,除此以外的特殊字符如果你要输出这些特殊字符的原形,你就可以用双引号或单引号引起来使其失去特殊含义。
< ,>,*,?,[,]对shell有特殊含义 但你可以用双引号引起来输入这些原形
讲了这么多大家是不是已经注意到所有的特殊字符在单引号中失去特殊含义,如果你要输出特殊字符原形但又记不清那些特殊字符在双引号中不能输出原形,建议你干脆用单引号引起来。
今天介绍条件测试语句
一、if 条件语句
格式:
if 条件表达式
then #当条件为真时执行以下语句
命令列表
else #为假时执行以下语句
命令列表
fi
if 语句也可以嵌套使用
if 条件表达式1
then
if 条件表达式2
then
命令列表
else
if 条件表达式3
then
命令列表
else
命令列表
fi
fi
else
命令列表
fi
你可以进行多层嵌套 一个if语句一定要跟一个fi 表示该层条件结束 否则会造成语法错误
结合前面讲的 举例如下:
这里先讲一个条件语句中用到的命令test 表示测试test后面的条件是否为真
if test -f "$1"
then
lpr $1
else
if test -d "$1"
then
cd $1
lpr $1
else
echo "$1不是文件或目录"
fi
fi
以上的例子还可以改成如下所示
if test -f "$1"
then
lpr $1
elif test -d "$1" #elif 同else if
then
(cd $1;lpr $1)
else
echo "$1不是文件或目录"
fi??????
以上的例子不知您是否看懂是什么意思吗?
假如我们现在将这个例子保存为prfile
chmod +x prfile
执行刚才的程序
./prfile aaa
这个例子是检查你的输入的参数是否是一个文件 如果是就打印 如果是一个目录 先转目录再打印 如果即不是文件也不是目录给出提示
二、多重条件测试语句case
格式:
case 字串 in
模式) 命令列表;;
模式) 命令列表;;
....
esac
多重条件语句是以case 开始以esac结束 中间可以有多个条件列表 功能是测试字串和和里面的模式有没有匹配的,有就执行里面的命令列表 模式也可以是*号 表示任意字串,每个模式里面的最后要心;;双引号结束,否则会发生语法错误。
现举例如下:
case $1 in
*.c)
cc $1
;;
*.txt)
lpr $1
;;
*)
echo "未知的类型"
esac
假如将以上内容保存在文件abc中
chmod +x abc
执行 ./abc a.c 将会对文件a.c进行编译
执行 ./abc readme.txt 将会把文件通过打印机
假如我将以上内容改一下,你是否会知道它的执行结果?
case $1 in
*)
cc $1
;;
*.txt)
lpr $1
;;
*.c)
echo "未知的类型"
esac
今天介绍循环语句
一. while 循环
while 命令格式
while 条件表
do
命令表
done
执行过程
shell首先执行条件表,如果条件表的最后一条语句的退出状态为零,则执行盾环体内的命令
表,执行完后,再检查条件表,如果退出状态为零将继续执行,如此循环往复直到条件表的
最后一条语句的退出状态非零. 退出状态为零就是条件为真True.
举例说明 假如shell文件的内容如下:
Sum=0
i=0
while true #true是系统的关键词 表示真
do
i=`expr $i + 1`
Sum=`expr $Sum + $i`
if [ $i = "100" ]
then
break;
fi
done
echo $i $Sum
最后这个程序显示的是 100 5050
这个程序的运算就是将1到100加起来
下面将这个程序再改动一下
Sum=0
i=0
while [ $i != "100" ]
do
i=`expr $i + 1`
Sum=`expr $Sum + $i`
done
echo $i $Sum
改动后的程序运算结果和上面是一样 但程序比上面的要简练
在这个循环中还可以以until做为测试条件 它正好与while测试的条件相反,也就是当条件为假时将继续执行循环体内的语句,否则就退出循环体,下面还用这个例子.
Sum=0
i=0
until [ $i = "100" ]
do
i=`expr $i + 1`
Sum=`expr $Sum + $i`
done
echo $i $Sum
当i不等于100时循环 就是当条件为假时循环,否则就退出,而第一个例子是当i不等于100
时循环,也就是测试条件为真时循环.
二.for 循环
命令格式:
for 变量 in 名字列表
do
命令列表
done
这里的名字列表是一个由空格分隔的字符串列表,shell在执行for循环时每次依次从名字表
中取出一个字符串赋给循环变量作为变量的值.
在写for语句时,也可以省略in 名字列表部分,这表示用当前的位置参数来代替这时的名
字列表.
下面举个例子
比如在你的电脑中有两个目录,一个是aa,一个是bb在这两个目录中有5个相同的文件,但其
中一个目录中的一个或多个文件刚刚修改过,现在我忘记刚才改的是那几个文件 了,那么我靠梢员冉弦幌抡饬礁瞿柯嫉奈募?椭?懒?程序如下:
for File in a1 a2 a3 a4 a5
do
diff aa/$File bb/$File
done
下面再举一个不带名字列表的例子
for File
do
echo $Filw
done
文件内容保存在a.sh中 并可执行
我们在执行这个shell程序时命令行如下:
a.sh a1 a2 a3 a4 a5
执行结果如下:
a1
a2
a3
a4
a5
大家从这个例子中可以看到命令行的参数被逐一读入一次
三.循环控制语句
break 命令不执行当前循环体内break下面的语句从当前循环退出.
continue 命令是程序在本循体内忽略下面的语句,从循环头开始执行.
一,命令组合:圆括号和花括号
shell中有两种方法将命令组合在一起:圆括号和花括号.圆括号使shell创建一个子shell
来读取并执行括起来的名命令.左括号和右括号不论出现在命令行中的什么位置,shell都会
认为它们具有特殊的组合意义的.只有用双引号将它们括起来引用,才表示圆括号或花括号
的原义.例如:
echo a(b)
将出现语法上的错误,要想输出a(b)字符串 只能括起来
echo "a(b)"
或echo a"("b")"
这样才能被shell正确解释.
利用组合命令有什么作用呢?
一,用圆括号组合命令
圆括号的组合命令可以创建子进程运行组合程序,建立子进程的功能是很有用的,因为
子shell在组合命令中的种种操作都不会影响到当前shell的各变量的值.
例如:
子进程在执行组合命令时改变了工作目录,并在新的工作目录下执行一系例命令,执行
完后它可以不必返回原工作目录,因为子进程工作目录的改变不会影响到当前工作目录.
创建子进程后将当前的环境也同样传给子shell,当前shell中用export输出到环境中的
各变量在子shell中同样有效.
花括号也可以将命令组合在一起.左 右花括号只有作为一条命令的第一个字出现时,
shell才它们含有特殊含义.
与圆括号不同的是花括号并不创建子shell,只是由当前的shell来读取并执行括起来的
命令.有时用户希望使用一组命令的顺序输出作为另一组命令的输入,此时用花括号是很方
便的.
不论是用圆括号不是花括号,退出状态都是等于最后一条括起来的命令的退出状态.
二,可以在当前shell中执行的命令
用户在使用shell时一定要了解那些是可以在当前shell中执行的命令 那些不可以
可以在当前shell中执行的命令有:
break case cd continue
echo eval exec exit
export for if read
readonly return set shift
test times trap umask
until wait while
: {}
[来源]http://www.7880.com/Info/Article-6b453e20.html
=============================================================
.chmod
chmod [who] operator [permission] filename
who
u 所有者
g 组
o 其他用户
a 所有用户
operator
+ 增加权限
- 取消权限
= 设定权限
permission
r 读权限
w 写权限
x 执行权限
s 文件属主和组set-ID
l 给文件加锁,使其他用户无法访问
t 粘性位 (如果一个目录上出现粘着位, 这就意味着目录中的文件只有其属主才可以删除,即使某个同组用户具有和属主同等的权限。不过有的系统上,这个规则并不严格; 如果在文件列表时看到t, 则意味着脚本或程序在执行时会被放在交换区(虚存),不过由于当今的内存价格如此这低,大可不必理会文件的t应用)
示例:
chmod a+x file
chmod og-w file
chmod g+w file
chmod u+x file
chmod go+x file
.suid/guid
chmod u+s file
# ls -l a.html
-rw-r--r-- a.html
# chmod u+s a.html
# ls -l a.html
-rwSr--r-- a.html
.find
find path -options [-print -exec -ok]
-exec find命令将匹配的文件执行exec所给出的shell命令 -exec cmd {} \; (注意: {} 和 \;间的空格)
-ok 同-exec只不过要求对命令的执行进行确认
-name 匹配文件名
find . -name "*.txt" -print
find . -name "[a-z]*" -print
find . -name * -print 或 find . -print
find . -name "[a-z][a-z][0--9][0--9].txt" -print
-perm 匹配权限
find . -perm 755 -print
find . -perm -007 -print
-prune 忽略目录 (如果使用了-depth选项,则忽略-prune选项) [没有试用成功]
find /apps -name "/apps/bin" -prune -o -print
-user 匹配用户
find . -user cnscn -print
-nouser 帐户属主已被删除的文件
find . -nouser -print
-group
-nogroup
-mtime +-n 按更改时间查找文件
find . -mtime -5 -print 查找5日内更改过的文件
find . -mtime +5 -print 查找5日前更改过的文件
-newer file 查找比file更改时间新的文件
! -newerfile2 查找比file更改时间旧的文件
find . -newer a.txt
find . ! -newer a.txt
# date
2006年 09月 13日 星期三 11:16:07 CST
# touch -t 0609120000 a.txt 创建文件a.txt并指定它的更改时间
# ls -l a.txt
-rw-r--r-- 1 root root 0 09-12 00:00 a.txt
-type
f
b
d
c
p
l
-maxdepth 指定递归操作的最在目录深度
# find . -maxdepth 1 -type d
.
./tmp
./mrtg-2.14.5
./piano
./tidy4aug00
-mount 仅在当前的文件系统内进行操作
-fstype
-cpio 将查询结果进行cpio命令进行操作
find etc home apps -depth -print | cpio -ivcdC65536 -o /dev/rmt0
-exec cmd {} \;
-ok cmd {} \;
find . -type f -exec ls -l {} \;
find . -type f -exec rm -f {} \;
find . -type f -ok ls -l {} \;
find . -type f -ok rm -f {} \;
-size n[c]
-depth
-follow
.xargs
功能类似 -exec , 但和-exec不同的是 它一次只是取得部分find查询到的文件结果, 而-exec是一次性获取全部文件结果,容易导致参数太多
# find . -type f -name "*.mp3" -print | xargs ls -l
-rw-r--r-- 1 root root 3985349 09-07 16:05 ./piano/025.mp3
-rw-r--r-- 1 root root 3936256 09-07 16:06 ./piano/duni.mp3
-rw-r--r-- 1 root root 28 09-07 16:23 ./piano/丝丝记忆.mp3
-rw-r--r-- 1 root root 2423745 09-07 16:24 ./piano/异国情.mp3
-rw-r--r-- 1 root root 2967512 09-07 16:20 ./piano/思乡曲.mp3
-rw-r--r-- 1 root root 4567040 09-07 16:20 ./piano/星空.mp3
.echo
echo -n "string..." 不换行输出
echo -e "string...\c" 同上
.read variable1 variable2 从标准输入读内容到变量
# read name
sssssssssss
# echo $name
sssssssssss
.文件重定向
cmd > file 结果输出到文件file
cmd >> file 结果附加到文件file
cmd 1> file 结果输出到文件file
cmd 2> file 标准错误输出到文件file
cmd > file 2>&1 结果和标准错误输出到文件file
cmd < file1 > file2 命令以file1为输入, 然后以file2为输出
cmd <<delimiter 从标准输入中读入, 直到遇到delimiter分界符
cat >>file <<HERE 把HERE间的内容发送给文件file, 不要忘记>>
>ssssssss
>ssaaaaaaa
>HERE
cmd <&m 把文件描述符m作为标准输入
cmd >&m 把标准输出重定向到文件描述符m中
cmd <&_ 关闭标准输入
.&&
cmd1 && cmd2 顺序执行命令cmd1和cmd2 (只有cmd1执行成功才会执行cmd2)
.||
cmd1 && cmd2 选择执行cmd1和cmd2(如果cmd1执行失败,则执行cmd2)
awk '{print $1,$2}' acc.qtr >qtr.tmp || echo "Error" #如果前面执行错误,则报告错误
.() 一般很少单独执行而是和&& || 组合运行
(cmd1;cmd2;cmd3...) 在当前shell中执行一组命令
mail ... || (echo "Error" | mail; exit)
.{} 一般很少单独执行而是和&& || 组合运行
{cmd1;cmd2;cmd3...} 在子shell中执行一组命令
.正则表达式
^ 匹配行首
$ 匹配行尾
* 匹配0个或多个前面的单个字符
[] 匹配[]内的任意一个字符
\ 转义
pattern\{n\} 匹配n次pattern
pattern\{n,\} 匹配最少n次pattern
pattern\{n,m\} 匹配n到m次pattern
经常使用的正则表达式
^
$
^[the]
[Ss]igna[lL]
[mayMAY]
^User$
[tty]$ 以tty结尾的行
\.
^d..x..x..x
^[^l]
[.*0]
[000*] 000或更多个
[iI] i或I
[iI][nN] in或iN或In或IN
[^$] 空行
^......$ 含6个字符的行
[a-zA-Z] 任意单个字符
[a-z][a-z]* 到少一个小写字母
[^0-9\$] 非数字或$
[^0-0A-Za-z] 非数字或字母
[123] 1或2或3
[Dd]evice device或Device
De..ce 以De开始中间两个任意字符最后是ce
\^q 以^q开始的行
^.$ 只有一个字符的行
^\.[0-9][0-9] 一个句点和两个数字开始的行
'"Device"' Device
De[Vv]ice\. Device 或 device
[0-9]\{2\}-[0-9]\{2\}-[0-9]\{4\} dd-mm-yyyy
[0-9]\{3\}\.[0-9]\{3\}\.[0-9]\{3\}\.[0-9]\{3\} 匹配IP地址
[^.*$] 匹配任意行
.grep
-E 匹配正则表达式
grep -ERv "a|g" ./ 查询不含字符a与g的文件
.awk
域分隔符
awk -F":" '{print $1}' a.txt
awk -F: '{print $1}' a.txt
awk脚本
awk -f a.wak a.txt
BEGIN/END
awk 'BEGIN {print "Name Belt\n-------------------"} {print $1"\t"$4} END{print "END..." } ' a.txt
$n ~ /正则/
awk '$0 ~ /Brown' a.txt
awk '$0 !~ /Brown/' a.txt
条件
awk '$3=="48" {print $0}' a.txt
awk '{if($3~/48/) print $0}' a.txt
awk '{if($3!~/48/) print $0}' a.txt
awk '$4 != "Tom" {print $0}' a.txt
awk '{if($6 <= $7) print $0 }' a.txt
awk '/[Gg]reen/' a.txt
awk '$1~/^ ... a/' a.txt
awk '$0 ~ /(Ye|Br)/' a.txt
awk '/^48/' a.txt
awk '{if($1=="Y" && $2=="G") print $0}' a.txt
awk '{if($1=="Y" || $2=="G") print $0}' a.txt
内置参数
ARGC 参数个数
ARGV 参数数组
ENVIRON 支持队列中系统环境变量的使用
FILENAME awk浏览的文件名
FNR 浏览文件的记录数
NR 已读出的记录数
FS 设置输入域分隔符,等 价于命令行-F选项
NF 记录的域的个数
OFS 输出域分隔符
RS 控制记录分隔符
# awk -F"S" '{print ENVIRON["HOME"] }' a.txt
/root
awk '{name=$1; belts=$4; if(belts ~ /Y/) print name" is belt" }' a.txt
awk '(total+=$6); END{ print "Total:" total}' 打印每一行及END一行
awk '{(total+=$6)}; END{ print "Total:" total}' 只打印END一行
ls -l | awk '/^[^d]/ {print $9"\t"$5} {total+=$5} END{print "Total: KB:" total}'
gsub(r,s) 在$0中用s替代r
#awk -F"S" 'gsub(/a/,"xxxxxxxxx"){print $0 }' a.txt
Return-Pxxxxxxxxxth: <[email protected]>
by mx28.mxxxxxxxxxil.sohu.com (Postfix) with ESMTP id 747AD00442AD
gsub(r,s,str) 在str中用s替代r
# awk -F":" 'gsub(/a/,"xxxxxxxxx",$1){print $0 }' a.txt
Return-Pxxxxxxxxxth <[email protected]>
by mx28.mxxxxxxxxxil.sohu.com (Postfix) with ESMTP id 747AD00442AD
for <cnstest%[email protected]>; Mon, 11 Sep 2006 18 03 11 +0800 (CST)
index(s,t) 返回字符串s中t的第一次出现的位置
length(s) 返回串s的长度
match(s,r) 测试s是否包含匹配r的字符串
# awk 'BEGIN{print match("ANCD",/d/)}'
0
# awk 'BEGIN{print match("ANCD",/D/)}'
4
split(s,arr,fs) 在fs上把分成数组arr, 返回数组长度
# awk 'BEGIN{print split("12#33#44#555#66",tmparr,"#")": "; print tmparr[0]" "tmparr[1]" "tmparr[3]}'
5: 12 44
sprint(fmt,exp) 返回经fmt格式化过的exp
sub(r,s) 用$0中最左边最长的子串代替s
# awk -F":" 'sub(/a/,"xxxxxxxxx"){print $0 }' a.txt
Return-Pxxxxxxxxxth: <[email protected]>
by mx28.mxxxxxxxxxil.sohu.com (Postfix) with ESMTP id 747AD00442AD
for <cnstest%[email protected]>; Mon, 11 Sep 2006 18:03:11 +0800 (CST)
substr(s,p) 返回s中从p开始的后续部分
substr(s,p,n) 返回字符串s中从p开始长度为n的后续部分
printf “%s\n”,"sssssssss"
- 左对齐
width 宽度
.prec 小数点右边的位数
%f 浮点数
#awk 'BEGIN{printf "%f\n",999}'
999.000000
%c 字符
%d 整数
%e 科学记数法
%g awk决定使用哪种浮点数
%o 八进制
%s 字符串
%x 十六进制
向awk传递参数
# awk '{ print AGE}' AGE=777 a.txt
777
777
FS的用法
#cat a.awk
!/bin/awk -f
BEGIN{
FS=":"
}
{
print $1
}
数组
# awk 'BEGIN{arr["a"]="b"; arr["b"]="c"; for(key in arr) print arr[key] }'
b
c
=======================================
.sed 是一个非交互性文本流编辑器
.sed [选项] sed命令 File
sed [选项] -f sed脚本 File
选项:
-n 不输出结果
-c
-f
命令:
p 打印匹配行
= 显示行号
s 替换
r 从另一个文件中读取文本
w 写文本到一个文本
q 第一个模式匹配完成后退出或立即退出
l 显示与八进制ASCII代码等价的控制字符
{} 在定位行执行的命令组
g 将模式2粘贴到/pattern n/
y 传送字符
n 延续到下一输入行,允许跨行的模式匹配语句
数据行定位
x x为一行号,如1
x,y 从x,到y的行
/pattern/ 包含模式的行/abc/或/[a-z]
/pattern/pattern/ 同时包含两个模式的行/disk/disks/
pattern/,x 在给定行号上查询含模式的行/disk/,3
x,/pattern/ 通过行号和模式查询匹配行 3,/disk/
x,y! 查询不含指定行号x和y的行, 如 1,2!
#head a.txt
Return-Path: <[email protected]>
Delivered-To: [email protected]
.在每一行后加入一行
#sed 'absssssssssssssss' a.txt (此处a为添加一行的命令, bssssss... 为要添加的内容)
Return-Path: <[email protected]>
bsssssssssssssss
Delivered-To: [email protected]
bsssssssssssssss
#sed -n '2p' a.txt (显示第二行)
Delivered-To: [email protected]
#sed -n '2,4p' a.txt (显示第二行到第四行)
Delivered-To: [email protected]
Received: from sohumx180.sohu.com (unknown [192.168.132.180])
by mx28.mail.sohu.com (Postfix) with ESMTP id 747AD00442AD
#sed -n '/sohu/p' a.txt (显示含sohu的行)
Delivered-To: [email protected]
Received: from sohumx180.sohu.com (unknown [192.168.132.180])
#sed -n '1,$p' a.txt (显示整个文件)
#sed -n 'p' a.txt
#sed -n '/.*ohu/p' a.txt (任意字符)
Delivered-To: [email protected]
Received: from sohumx180.sohu.com (unknown [192.168.132.180])
by mx28.mail.sohu.com (Postfix) with ESMTP id 747AD00442AD
#sed -n '$p' a.txt (显示第2行)
Delivered-To: [email protected]
#sed -ne '/sohu/p' -e '/sohu/=' a.txt (显示文本及行号)
Delivered-To: [email protected]
2
Received: from sohumx180.sohu.com (unknown [192.168.132.180])
3
by mx28.mail.sohu.com (Postfix) with ESMTP id 747AD00442AD
4
.$cat a.sed (sed脚本)
#!/bin/sed -f
/sohu/ a\ 在含sohu的行后添加一行,内容为hello....
hello.....
执行脚本
#./a.sed a.txt
Return-Path: <[email protected]>
Delivered-To: [email protected]
hello.....
Received: from sohumx180.sohu.com (unknown [192.168.132.180])
hello.....
.$cat a.sed (sed脚本)
#!/bin/sed -f
/sohu/ i\ 在含sohu的行前添加一行,内容为hello....
hello.....
#./a.sed a.txt
Return-Path: <[email protected]>
hello.....
Delivered-To: [email protected]
hello.....
Received: from sohumx180.sohu.com (unknown [192.168.132.180])
.$cat a.sed (sed脚本)
#!/bin/sed -f
/sohu/ c\ 替换含sohu的行为行hello....
hello.....
# ./a.sed a.txt
Return-Path: <[email protected]>
hello.....
hello.....
hello.....
hello.....
.$cat a.sed (sed脚本)
#!/bin/sed -f
3 c\ 把第3行替换为hello....
hello.....
#./a.sed a.txt
Return-Path: <[email protected]>
Delivered-To: [email protected]
hello.....
#sed '1d' a.txt 删除第一行
Delivered-To: [email protected]
Received: from sohumx180.sohu.com (unknown [192.168.132.180])
#sed '1,2d' a.txt 删除第一到第2行
Received: from sohumx180.sohu.com (unknown [192.168.132.180])
by mx28.mail.sohu.com (Postfix) with ESMTP id 747AD00442AD
#sed 's/sohu/xxxxxxxx/g' a.txt 把sohu替换为xxxxxxxxxx
Return-Path: <[email protected]>
Delivered-To: [email protected]
#sed 's/sohu/xxxxxxxx/gw b.txt' a.txt 把sohu替换为xxxxxxxxxx, 并把替换的内容输出写到b.txt
Return-Path: <[email protected]>
Delivered-To: [email protected]
#cat b.txt
Delivered-To: [email protected]
Received: from xxxxxxxxmx180.sohu.com (unknown [192.168.132.180])
>-------by mx28.mail.xxxxxxxx.com (Postfix) with ESMTP id 747AD00442AD
>-------for <cnstest%[email protected]>; Mon, 11 Sep 2006 18:03:11 +0800 (CST)
>-------by xxxxxxxxmx180.sohu.com (Postfix) with SMTP id 7F69E05B70E1
>-------for <[email protected]>; Mon, 11 Sep 2006 18:03:10 +0800 (CST)
To: [email protected]
$sed '/sohu/r b.txt' a.txt 把b.txt的内容,附加到含有sohu的行的后面
#sed '/sohu/q' a.txt 第一次匹配后退出
Return-Path: <[email protected]>
Delivered-To: [email protected]
相关阅读 更多 +