linux_shell编程总结(一)基本功
一个编程语言,一段时间不写,就容易忘记。
(想法:要么语言单一,要么设计友好,否则像现在这样几个语言切换,真是要了程序员的脑袋命了)
摘录备忘。
?
?在当前目录下查找文件权限位为755的文件,即文件属主可以读、写、执行,其他用户可以读、执行的文件
???? find . -perm 755 -print?
?在当前目录下查找除目录以外的所有类型的文件
???? find . ! -type d -print??
?用ls -l 命令列出所匹配的文件
???? find . -type f -exec ls -l {} \;
?在/logs目录中查找更改时间在5日以前的文件并删除它们
???? find logs -type f -mtime +5 -exec rm {} \;
(7)echo
?作用:显示文本行或变量,或者把字符串输入到文件
?格式:echo string
?例:
??给出提示符,并输入值给变量name
???echo "What's your name:\c"
???read name
(8)pg
?作用:显示文件
?格式:pg filename
(9)read
?作用:读入值给变量
?格式:read var
?例: read name?从键盘读入字符到name变量
(10)cat
?作用:显示文件
?格式:cat filename
(11)tee
?作用:把输出的一个副本输送到标准输出,另一个副本拷贝到相应的文件中
?格式:tee filename
?例:who | tee who.out?使用who命令,结果输出到屏幕上,同时保存在who.out文件中
(12)grep(全局正则表达式)
?作用:允许对文本文件进行模式查找,如果找到匹配模式,grep打印包含模式的所有行
?格式: grep [options] 基本正则表达式? [文件]
?常用options值:
??-c 只输出匹配行的计数
??-i 不区分大小写(只适用于单字符)
??-h 查询多文件时不显示文件名
??-l 查询多文件时只输出包含匹配字符的文件名
??-n 显示匹配行及行号
??-s 不显示不存在或无匹配文本的错误信息
??-v 显示不包含匹配文本的所有行
?例:grep "sort" *.doc?在当前目录下所有的.doc文件中查找字符串"sort"
???? grep "48<tab>" data.f?抽取字符串后有一个<Tab>键
???? grep '[0-9]\{3\}\.[0-0\[3\}\.' ipfile?要抽取其中所有nnn.nnn的IP地址(原文印刷错误?)
(13)awk
?格式: awk [-f field-separator] 'command' input-file(s)
=====================================================================================
???awk条件操作符
=====================================================================================
操作符??描述????????? 操作符??描述
<???????? 小于????????? >=?????? 大于等于
<=?????? 小于等于????~???????? 匹配正则表达式
==?????? 等于????????? !????????? 不匹配正则表达式
!=?????? 不等于???
=====================================================================================?
awk内置变量
------------------------------------------------------
ARGC??命令行参数个数
ARGV??命令行参数排列
ENVIRON??支持队列中系统环境变量的使用
FILENAME?awk浏览的文件名
FNR??浏览文件的记录数
FS??设置输入域分隔符,等价于命令行-F选项
NF??浏览记录的域个数
NR??已读的记录数
OFS??输出域分隔符
ORS??输出记录分隔符
RS??控制记录分隔符
?注:awk中所采用的正则表达式的符号要比grep和sed多两个:+(匹配一个或多个字符),?(匹配模式出现率)
?例:
??awk '{if($4~/Brown/) print $0}' grade.txt 如果field-4包含了Brwon,打印该行
??awk '$3 == "48" {print $0}' grade.txt?? 精确匹配,如果field-3等于了 "48",则打印该行
??awk '{if( $1=="p1" && $4=="p2" ) print $0}' grade.txt 同时满足两个条件,则打印该行
??awk '{if( $1=="p1" || $4=="p2" ) print $0}' grade.txt 只要满足其中一个条件,则打印该行
(14)expr?用于计算或数值测试
?格式:expr argument operator argument
?例:?expr 10 + 10?其结果为20
??expr 30 / 3?其结果为10
??expr 30 \* 3?其结果为90,使用乘号时,必须用反斜线屏蔽其特定含义。
??expr rr + 1 ?当rr非整数时,将返回错误,此处为"expr:non-numeric argument"
2.文件名的匹配
?特殊的匹配符号:
?*?匹配文件名中的任何字符串,包括空字符串
???匹配文件名中的任何单个字符串
?[...]?匹配[]中包含的任何字符
?[!...]?匹配[]中非感吧号!之后的字符
?例:
??显示所有以.doc结尾的文件名
???ls *.doc
??显示以cl开头,后面跟任何字符串,最后以.sed结尾的文件名
???ls cl*.sed
??显示任意两个字符开头,接着是r,后面跟任何字符的文件
???ls ??r*
??显示以i或o开头的文件名
???ls [io]*
??匹配所有以log.开头,后面跟随一个数字,然后可以是任意字符串的文件名
???ls log.[0-9]*
??匹配所有以log.开头,使用[!0-9]来表示非数字开头的字符串
???ls log.[0-9]*
3.文本过滤
=====================================================================================
???基本元字符集及其含义
=====================================================================================
^?????????????????????? 只匹配行首
$???????????????????????只匹配行尾
*???????????????????????一个单字符后紧跟*,匹配0个或多个此单字符
[]???????????????????????匹配[]内字符。可以是一个单字符,也可以是字符序列,用-表示范围
?????????????????????????如用[1-5]代替[12345]
\????????????????????????用来屏蔽一个元字符的特殊含义。如$ . ' " * ^ | ( ) \ + ?
.?????????????????????????匹配任意单字符
pattern\{n\}????? 用来匹配前面pattern出现次数。n为次数
pattern\{n,\}m??含义同上,但次数最少为n
pattern\{n,m\}??含义同上,但pattern出现次数在n与m之间
=====================================================================================
例:
?^$?匹配一个空行
?^.$?匹配只包含一个字符的行
?compu*t 匹配字符u 0次或多次,这个可匹配computer,
?A\{2\}B 匹配字母A出现两次,并以B结尾
?A\{2,4\}B 匹配字母A出现2到4次之间
4.特定shell变量
=====================================================================================
$#?传递到脚本的参数个数
$*?以一个单字符串显示所有向脚本传递的参数。与位置变量不同,此选项参数可超过9个
$$?脚本运行的当前进程ID号
$!?后台运行的最后一个进程的进程ID号
$@?与$#相同,但是使用时加引号,并在引号中返回每个参数
$-?显示shell使用的当前选项,与set命令功能相同
$??显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误
=====================================================================================
其他:$0(脚本名字) $1 $2 $3 ...$9
5.shell输入与输出
?
5.1文件描述符
=====================================================================================
?文件描述符? 文件?
?0?????????????? 输入文件——标准输入
?1?????????????? 输出文件——标准输出
?2?????????????? 错误输出文件——标准错误
=====================================================================================
注:?标准输入是文件描述符0,它是命令的输入,缺省是键盘,也可以是文件或其他命令的输出
?标准输出是文件描述符1,它是命令的输出,缺省是屏幕,也可以是文件
?标准错误是文件描述符2,它是命令错误的输出,缺省是屏幕,也可以是文件
5.2重定向:<,<<,>,>>
=====================================================================================
command>filename??把标准输出重定向到一个新文件中
command>>filename??把标准输出重定向到一个文件中(追加)
command 1>filename??把标准输出重定向到一个新文件中
command>filename 2>&1??把标准输出和标准错误一起重定向到一个文件中
command 2>filename??把标准错误重定向到一个新文件中
command 2>>filename??把标准错误重定向到一个文件中(追加)
command >>filename 2>&1 ?把标准输出和标准错误一起重定向到一个文件中(追加)
command <filename >filename 2?command命令以filename文件作为标准输入,以filename2文件作为标准输出
command <&m???把文件描述符m作为标准输入
command >&m???把标准输出重定向到文件描述符m中
command <&-???关闭标准输入
=====================================================================================
例:
#############################################################################
#! /bin/sh
# f_desc
#把文件描述符4指定为标准输入,然后打开stock.txt文件
exec 4<&0 0<stock.txt
#读入2行文本
read line1??
read line2??
#作为标准输入的文件描述符4被关闭
exec 0<&4
#显示两个变量的内容?
echo &line1??
echo &line2
#############################################################################
5.3管道:?命令1|命令2
who | awk '{print $1"\t"$2}'
6.条件测试
格式1:test condition
格式2:[condition]
=====================================================================================
???文件测试状态
=====================================================================================
-d?目录??????? -s?文件长度大于0,非空
-f?正规文件???-w?可写
-l?符号链接???-u?文件有suid位设置
-r?可读???????? -x?可执行
=====================================================================================
组合测试:?-a 逻辑与?-o逻辑或?!逻辑否
例: ?[-w results.txt -a -w scores.txt
?echo $?
?检查上面两个文件是不是都是可写的
字符串测试?string_operator 可为=(相等)? !=(不相等)? -z(空串) -n(非空串)
格式1:test "string"
格式2:test string_operator "string"
格式3:test "string" string_operator "string"
格式4:[string_operator string]
格式5:[string string_operator string]
数值测试?numeric_operator可为 -eq(相等),-ne(不相等),-gt(大于),-lt(小于),-le(小于等于),-ge(大于等于)
格式1:"number" numeric_operator "number"
格式2:["number" numeric_operator "number"]
7.命令执行顺序 && ,||, (), {}
&&
格式:命令1 && 命令2
说明:命令1返回真(即返回0,成功被执行)后,命令2才能够被执行
例:/apps/bin目录将会被移到/apps/dev/bin目录下,如果它没有被成功的执行,就不会删除/apps/bin目录
?mv /apps/bin /apps/dev/bin && rm -r /apps/bin
||
格式:命令1 || 命令2
说明:命令1未执行成功,那么就执行命令2
例:?拷贝文件没成功的话,就显示错误.
?cp word.txt word.bak || echo "cp file failed!"
() {}
格式:(命令1;命令2;...) {命令1;命令2;...}
8.控制流结构 if...then...else...fi,case,for,until,while,break,continue
1)返回码
?观察:echo $?
?退出:exit n?(n为一数字)
?break n??==>跳出指定的循环个数。如break 2则跳出2个循环
?continue?==>跳出循环当前步
2)流控制if...then...else...fi
?if condition1
??then
????? command1
?elif condition2
??then
????? command2
?else
??command3
?fi
例1:
##############################################
#! /bin/sh
# ifwr
LOGFILE=test.txt
echo $LOGFILE
if [ ! -w "$LOGFILE" ]; then
?echo "You cannot write to $LOGFILE " >&2
fi
##############################################
例2:
##############################################
#! /bin/sh
# ifcp
#下面用2>&1重定向标准错误,去除了系统产生的错误和系统输出
if cp myfile myfile.bak >/dev/null 2>&1 ; then
?echo "good copy"
else
?echo "`basename $0`:error could not copy the files " >&2
fi
##############################################
例3:
##############################################
#! /bin/sh
# ifcp
#将脚本参数传入系统命令
#此处检测目录是否为空
DIRECTORY=$1
if [ "`ls -A $DIRECTORY`" = ""] ; then?#也可用 if [$# -lt 1] 来代替判断语句
?echo "$DIRECTORY is indeed empty"
else
?echo "$DIRECTORY is not empty " >&2
fi
##############################################
例4:
##############################################
#! /bin/sh
# ifmkdir
#将脚本参数传入系统命令
#此处检测目录是否为空
DIRECTORY=$1
if [ "$DIRECTORY" = ""] ; then
?echo "Usage: `basename $0` directory to create"
?exit 1
fi
if [ -d $DIRECTORY ]
then : # do nothing
else
?echo "The directory does exist"
?echo -n "Create it now? [y..n] :"
?read ANS
?if [ "$ANS" = "y" ] || [ "$ANS" = "Y" ]
?then
??echo "creating now"
??mkdir $DIRECTORY >/dev/null 2>&1
??if [ $? != 0 ]; then
???echo "Errors createing the directory $DIRECTORY" >&2
???exit 1
??fi
?else : # do nothing
?fi
fi
##############################################
3)case控制流
?case语句为多选择语句。可以用case语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。
?格式:
==========================================================================
?case 值 in
?模式1)
??命令1
??....
??;;
?模式2)
??命令2
??....
??;;
?esac
==========================================================================
注:每一模式必须以右括号结束,取值可以为变量或常数。
匹配发现取值符合某一模式后,其间所有命令开始执行直至“;;”
取值将检测匹配每一个模式,一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。
如果无一匹配模式,使用星号*捕获该值,再接受其他输入
?
模式部分可能包括元字符,与在命令行文件扩展名例子中使用过的匹配模式类型相同,即
*(任意字符),?(任意单字符),[..](类或范围中任意字符)?
例1:
##############################################
#! /bin/sh
# caseterm
echo "choices are..vt100,vt102,vt220"
echo -n "enter your terminal type :"
read TERMINAL
case $TERMINAL in
?vt100|vt102)?TERM=vt100
??;;
?vt220)?TERM=vt220
??;;
?*)?echo "`basename $0`:Unknow response" >&2
???echo "setting it to vt100 anyway,so there"
???TERM=vt100
??;;
esac
export TERM
echo "Your terminal is set to $TERM"
##############################################
例2:
##############################################
#! /bin/sh
# caseparam
if [ $# !=1 ] ; then
?echo "Usage:`basename $0` [start|stop|help]" >&2
?exit 1
fi
#assign the parameter to the variable OPT
OPT=$1
case $OPT in
?start)?echo "starting..`basename $0`"
??;;
?stop)?echo "stopping..`basename $0`"
??;;
?help)
??;;
?*)?echo "Usage:`basename $0` [start|stop|help]"
??;;
esac
##############################################
4)循环
for格式
==========================================================================
for 变量名 in 列表
do
??? 命令1
??? 命令2
??? .....
??? 命令n
done
==========================================================================
注:列表可以包含替换,字符串和文件名
例1:
##############################################
#! /bin/sh
# for_i
for loop in 1 2 3 4 5 ?#for loop in "orange red blue grey"
do
??? echo $loop
done
##############################################
例2:
##############################################
#! /bin/sh
# for_ls
for loop in `ls `
do
??? echo $loop
done
##############################################
例3:
#for params,不使用in列表选项时,实际上等价于
#for params in "$@" 或
#for params in "$*"
##############################################
#! /bin/sh
# for_param
for loop in "$@"?# 也可以是"$*," 这可以从命令行中取得参数
do
??? echo $loop
done
##############################################
until(不常用)格式
==========================================================================
until 条件
do
??? 命令1
??? 命令2
??? .....
??? 命令n
done
==========================================================================
例1:监视文件系统容量,当它达到一定水平时通知超级用户
##############################################
#! /bin/sh
# until_mon
LOOK_OUT=`df | grep /logs | awk '{print $5}' | sed 's/%//g'`
echo $LOOK_OUT
until ["$LOOK_OUT" -gt "90" ]
do
??? echo "Filesystem..logs is nearly full" | mail root
??? exit 0
done
##############################################
while格式
==========================================================================
while 命令
do
??? 命令1
??? 命令2
??? .....
??? 命令n
done
==========================================================================
例1:从文件中读取数据,使用重定向以保证从文件中读取数据
#########################################################################
#! /bin/sh??|?SAVEDIFS=$IFS
# whileread??|?IFS=:
while read LINE??|?while read NAME DEPT ID
do ???|?do
??? echo $LINE??|???? echo -e "$NAME\t $DEPT\t $ID"
done <names.txt??|?done <names.txt
???|?IFS=$SAVEDIFS
#########################################################################
上面右边使用IFS将域分隔符改为;号而不是空格或tab键
测试数据names.txt:
Louise Conrad:Accounts:Acc889
Peter James:Payroll:PR483
#########################################################################
死循环格式
while :
do
??? 命令
done
例2:
#########################################################################
#! /bin/sh
# menu
#set the date,user and hostname up
MYDATE=`date +%d/%m/%Y`
THIS_HOST=`hostname -s`
USER=`whoami`
#loop forever !
while :
do
??? # clear the screen
??? tput clear
??? # here documents starts here
??? cat <<MAYDAY
---------------------------------------
?User:$USER??Host:$THIS_HOST??Date:$MYDATE
---------------------------------------
??1 : List files in current directory
??2 : Use the vi editor
??3 : See who is on the system
??H : Help screen
??Q : Exit Menu
---------------------------------------
MADAY
??? # here document finished
??? echo -e "\tYour Choice [1,2,3,H,Q] >"
??? read CHOICE
??? case $CHOICE in
??????? 1) ls???
??????????? ;;
??????? 2) vi
??? ???? ;;
??????? 3) who
??? ???? ;;
??????? H|h)
??? cat <<MAYDAY
?this is the help screen,nothing here yet to help you !
??? MAYDAY
???? ;;
??????? Q|q) exit 0
??? ???? ;;
??????? *) echo -e "\t\007Unknown user response"
??? ???? ;;
??? esac
??? echo -e -n "\tHit the return key to continue"
??? read DUMMY
done
#########################################################################
等我总结完了,后面又翻了一本书《Linux 编程命令详解》第二版,Richard Petersen著,梁普选,刘玉芬 等译,2001年由电子工业出版社出版的,这本书总结得更好了。呵呵,看来,凡事都是有个过程的。
?
?
===================================================================
?????????????????????? 特殊符号的总结
1、{} 大括号: 用法一:通配符扩展 eg: ls my_{finger,toe}s 这条命令相当于如下命令的组合: ls my_fingers my_toes eg: mkdir {userA,userB,userC}-{home,bin,data} 我们将得到 userA-home, userA-bin, userA-data, userB-home, userB-bin,userB-data,userC-home, userC-bin, userC-data,这几个目录 用法二:可用于语句块的构造,语句之间用回车隔开。如果你想在某些使用单个语句的地方(比如在AND或OR列表中)使用多条语句,你可以把它们括在花括号{}中来构造一个语句块。 eg: { grep -v "$cdcatnum" $strack_file > $temp_file cat $temp_file > $strack_file echo cat -n file1 } (注:以上大括号中的四句命令够成了一个语句块) 用法三:参数扩展 ${name:-default} 使用一个默认值(一般是空值)来代替那些空的或者没有赋值的变量name; ${name:=default}使用指定值来代替空的或者没有赋值的变量name; ${name:?message}如果变量为空或者未赋值,那么就会显示出错误信息并中止脚本的执行同时返回退出码1。 ${#name} 给出name的长度 ${name%word} 从name的尾部开始删除与word匹配的最小部分,然后返回剩余部分 ${name%%word} 从name的尾部开始删除与word匹配的最长部分,然后返回剩余部分 ${name#word} 从name的头部开始删除与word匹配的最小部分,然后返回剩余部分 ${name##word} 从name的头部开始删除与word匹配的最长部分,然后返回剩余部分 (注,name为变量名,word为要匹配的字符串) 用法三在处理字符串和未知变量时,是很有用的。
2、[] 中括号:
用法一:通配符扩展: 允许匹配方括号中任何一个单个字符 eg: ls /[eh][to][cm]* 相当于执行 ls /etc /home(若有/eom目录,就相当于会执行ls /etc /home /eom) 注:在mkdir命令下不能扩展
用法二:用于条件判断符号: []符号可理解为指向test命令的一个软链接,所以其用法可完全参照test,将test位置替换为[便可。 eg: if [ "$?"?!= 0 ] 等价于 if test "$?"?!= 0 then echo "Executes error"
3、`command` 反引号:`command`与$(command)的含义相同,都是返回当前执行命令的结果
eg: #!/bin/sh for file in $(ls f*.sh);do lpr $file done exit 0 该例实现了扩展f*.sh给出所有匹配模式的文件的名字。
4、'string' 单引号 和 "string" 双引号
双引号:如果想在定义的变量中加入空格,就必须使用单引号或双引号, 单、双引号的区别在于双引号转义特殊字符而单引号不转义特殊字符 eg: $ heyyou=home $ echo '$heyyou' $ $heyyou ($没有转义) eg: $ heyyou=home $ echo "$heyyou" $ home (很明显,$转义了输出了heyyou变量的值)
5、$# 它的作用是告诉你引用变量的总数量是多少;
$$ 它的作用是告诉你shell脚本的进程号; $* 以一个单字符串显示所有的脚本传递的参数。等价于$1 $2 $3.......; $@ 与$*基本类似(参见序号7),但在数组赋值时有些不同; $? 前一个命令的退出码; $- 显示shell使用的当前选项; $! 最后一个后台运行的进程ID号。
6、$((...))语法:对括号内的表达式求值(fantaxy注:千万别乱加入空格)
eg: #!/bin/sh x=0 hile [ "$x" -ne 10 ];do echo $x x=$(($x+1)) done exit 0
7、shell中几种特殊的参数变量的引用
$1、$2、$3……${10}、${11}、${12}…… :表示脚本传入的的各个参数,注意当需表示两位数以后的参数时数字要用花括号括起。 $@ 列出所有的参数,各参数用空格隔开 $*: 列出所有的参数,各参数用环境变量IFS的第一个字符隔开
8、命令列表:
AND列表 statement1 && statement2 && statement3 && …:只有在前面所有的命令都执行成功的情况下才执行后一条命令 OR列表 statement1 || statement2 || statement3 || …:允许执行一系列命令直到有一条命令成功为止,其后所有命令将不再被执行 eg:#!/bin/sh touch file_one rm -f file_two if [ -f file_one ] && echo "hello" && [ -f file_two ] && echo " there" then echo "in if" else echo "in else" fi exit 0 上例的输出为: hello in else 关于AND列表与OR列表,在逻辑判断中很使用,下面就举一个其最常用的例子: [ condition ] && command for true || command for false: 当条件为真时,执行commandfor true ,当条件为假时,执行command for false
9、: 冒号:内建空指令,返回值为0
eg: $?: $ echo $? $ 0 while: (该语句结构可实现一个无限循环)
10、; 分号: 在 shell 中,担任"连续指令"功能的符号就是"分号"
eg:cd ~/backup?; mkdir startup?; cp ~/.* startup/.
11、# 井号:表示符号后面的是注解文字,不会被执行;
* 匹配文件名中的任何字符,包括字符串; ? 匹配文件名中的任何单个字符。 ~ 代表使用者的 home 目录
12、\ 倒斜线:放在指令前,有取消 aliases(别名) 的作用;放在特殊符号前,则该特殊符号的作用消失;放在指令
的最末端,表示指令连接下一行(使得回车符无效,只起换行作用)
14、! 感叹号:通常它代表反逻辑的作用,譬如条件侦测中,用?!= 来代表"不等于"
15、** 次方运算:两个星号在运算时代表 "次方" 的意思
eg:let "sus=2**3" echo "sus = $sus" $ sus = 8
?
?
?
?