您的位置:首页 > 运维架构 > Shell

shell是一种程序

2010-05-22 22:41 309 查看
shell是一种程序;
shell扫描命令行,判断要执行的程序名称以及要传该该程序的参数;可能会执行一些特殊字符的替换;如*、?、[...]等;<、>、>>、|等;

正则表达式
.:匹配任何字符;

工具

ed工具:

常用命令:
ed filename;
1,$p //显示所有行;
1,$s/oid/OID/g //用OID替换oid;
/ ... / //搜索前后都有空格的任意三个字符;
/ //重复搜索;
/^the/ //搜索以the开头的行;^ 表示行首匹配;
1,$s/^/>>/ //在每行开头插入>>;
1,$s/$/>>/ //在每行末尾添加>>,$匹配行结束;
/转义字符
1,$s/..$// //删除每行最后2个字符;
^$ //匹配不含字符的行;
/[tT]he //搜索the或The; [0123456789] = [0-9]
1,$s/[aeiouAEIOU]//g //删除所有元音字母;
一般来说,诸如*、.、[...]、$和^等正则表达式特殊符号,只有在搜索串中才有特殊意义,而在替换串中没有特殊意义;
如果左方括号后的第一字符是^,那么匹配的意思是反过来;如:[^A-Z]匹配除大写字母以外的任何字符;
*,在构成正则表达式时,用星号来匹配0或若干个紧靠在星号前的字符;如X*;
正则表达式总是寻求最大匹配,所以 .* 匹配一行;
如果要把连字符放在方括号中作为可选的字符,必须把它放在紧跟左方括号的位置如:[-0-9];[^-0-9];
X/{1,10/} //匹配1至10个连续的X;前后数字可以相同;
X/{5,/} //匹配至少5个连续的X;
/(.../) //保存匹配的字符串;把字符串包括在前加反斜杠的小括号中,可以捕获正则表达式匹配的字符串,捕获的字符串存储在编号为1到9的寄存器中;如:
^/(./) //匹配行首的第一个字符,并将该字符存到1号寄存器中;用/n来引用存在寄存器中的内容;因此:
^/(./)/1 //匹配的是一行的头两个字符相同;
^/(./).*/1$ //匹配一行中的头一个字符(^.)跟最后一个字符(/1$)相同的行。
/(.../) //把内容赋给下一个的寄存器;如
^/(.../)/(.../) //行中头三个字符存在1号寄存器中,接着三个字符存在2号寄存器中;
1,$s//(.*/) /(.*/)//2 /1/ //交换两个字段;其中/(.*/) /(.*/)表示匹配制表符(右小括号和反斜杠之间的字符)之间的所有字符并将它们赋给1号寄存器,匹配制表符之后的所有字符并将它们赋给2号寄存器;

cut工具

从数据文件或命令的输出中析取各种各样的数据域;
一般格式:cut –cchars file;如cut –c2-5 file;把每行的第二个到第五个字符取出来;
cut可以从标准输入读取;如who | cut –c1-8,18-
另一种格式:cut –ddchar –ffields file;dchar是数据中分隔各字段的分隔符,默认的分隔符是制表符,fields表示要从文件file中析取出来的字段;如:cut –d: -f1,6 /etc/passwd;
附:sed –n l file;会显示file中的制表符为’/t’;

paste工具

把多个文件中的对应行合在一起;paste files;之间的分隔符是制表符;
如:paste names addresses numbers
-d选项:如paste –d ‘+’ names addresses numbers ;指定分隔符
-s选项:把同一个文件中的行粘在一起;
sed工具
意指流编辑器(stream editor),与ed不同,sed不能用于交互;
一般格式:sed command file;如sed ‘s/OID/oid/’ file;用oid替换OID;处理的是每行的第一个;
sed处理的是临时文件,可以这样做:
sed ‘s/OID/oid/’ file > tmp
mv tmp file
sed ‘s/OID/oid/g’ file 处理的是一行中的多出;
-n选项:从文件中析取几行;如sed –n ‘1,2p’ file 只显示前两行
p命令;sed –n ‘/OID/p’ file 只打印包含OID的行;
d命令;sed ‘1,2d’ file 删除掉第一和第二行
sed ‘/oid/d’ file 删除包含oid的行
sed ‘s/...//’ file 删除file文件每一行的前三个字符

tr工具

过滤器tr用来转换来自标准输入的字符;一般格式:tr from-chars to-chars;
如:tr e x < file,处理文件需要重定向;
cut –d: -f1,6 /etc/passwd | tr : ‘ ’
处理范围:tr ‘[a-z]’ ‘[A-Z]’ < file
-s选项:用来压缩to-chars中重复的字符;如:
tr –s ‘ :’ ‘/11’ 输入中的一个或多个连续的冒号在输出中都被替换成一个制表符;
-d选项;删除输入流中的字符;如:
tr –d ‘ ‘ < file == sed ‘s/ //g’ file
grep工具
-i选项;表示不区分大小写;
-v选项;表示不包含那些行;如:grep –v ‘unix’ file
-l选项;只给出包含给定模式的文件列表,而不给出文件中的匹配行;如:grep –l ‘oid’ *.c
-n选项;显示行号;

sort工具

取出指定输入文件的每一行,将它们按升序排序;
-u选项;在输出中去除重复的行;
-r选项;颠倒排序顺序;
-o选项;指定输出文件;sort names >file == sort names –o file
但是sort names >names不行;而sort names –o names可以;
-n及+1n;指定某个字段排序;字段之间用空格或制表符分隔;而可以用-t指定分隔符;如:
sort +2n –t: /etc/passwd

uniq工具

可以先排序在使用该工具;如:sort names | uniq
-d选项;找出文件中有哪些重复行;

shell编程初步

操作符前后不能加空格;
echo $variable
对于命令:x=*;echo $x的执行;shell在给变量赋值时不进行文件名替换;即echo *;
mv $filename ${filename}X;把文件名后面加字母X;当变量名后面要跟字母、数字或下划线时,才有必要使用大括号;
算术扩展的格式:$((expression));如echo $((i+1));

引用

单引号;告诉shell忽略所包含的所有特殊字符,双引号只要求忽略大多数,不被忽略的特殊字符:美元符号、反引号、反斜杠;
双引号中不做文件名替换;
反引号;告诉shell执行括起来的命令,等同于$(command),但不如$()好理解;
如:mail $(sort –u names) < memo
expr命令:如expr 17 /* 6 ;结果是102,需要把操作符和操作数作为分开的参数;只计算整数算术表达式,浮点数可以用awk和bc命令;

参数传递

每当执行shell程序时,shell自动把第一个参数存在一个特殊的shell变量1中,第二个参数存在变量2中,以此类推;如引用第一个参数:$1; who | grep $1;
$#里面存放的是命令行中的参数个数;
$*表示传递给程序的所有的参数;
shell先替换变量名,然后把命令行划分为各个参数;
几个小程序:
查找:grep ‘‘$1’’ phonebook
添加:echo ‘‘$1 $2’’ >> phonebook
sort –o phonebook phonebook
删除:grep –v ‘‘$1’’ phonebook > /tmp/phonebook
mv /tmp/phonebook phonebook
传递9个以上的参数:${n}
shift命令是把位置参数左移;即原来存在$2中的任何内容赋给$1,等,且$#自动减1;shift也可以指定移动的个数;如:shift n;

判断

if命令格式:
if commandt
then
command
command
...
fi
其中,commandt需要执行并检测退出状态,如果退出状态为0,则执行其后then和fi自己的命令;
程序退出为0时通常表示运行成功;
shell自动将最后所执行命令的退出状态设置到shell变量$?中;
当不需要命令的输出结果时,可以把输出重定向到系统的垃圾桶--/dev/null中,从它读取的是文件结束符;
如下命令: who | grep “^$user ” > /dev/null
test命令;经常用来在if命令中测试一种或几种条件;格式:test expression
如:test “$name” = fred
其中对双引号的说明:如果没有使用引号,当name为空时,test得到的参数只有两个,即=和fred;而当有引号时,得到的是null、=和fred;
检测字符串的操作符:=、!=、string、-n string、-z string;其中-n理解为检测长度是否不为0,-z检测长度是否为0或是否为空;
test X”$symbol” = X ;判断symbol是否为空;
等号操作符的优先级比-z的高;
test expression 等价于 [ expression ] ;其中[为命令,但该命令后面需要跟随]
test整数操作符:-eq 、-ge、-gt、-le、-lt、-ne;
test文件操作符:-d 为目录、-e 存在、-f 为普通文件、-r 为进程可读文件、-s 长度不为0、-w 为进程可写文件、 -x 可执行、-L 为符合化链接;
逻辑非: ! ;逻辑与: -a ;逻辑或:-o;其中-o优先级小于-a;
小括号:()可以改变求值顺序;但小括号对shell具有特殊意义;需要转义;且需要空格隔开,如:[ /( “$count” –ge 0 /) –a /( “$count” –lt 10 /) ]
else结构;
exit命令;内部命令,立即终止shell程序的执行;exit n;n为退出状态;
elif命令,格式和c的else if类似;
date +%H;可以直接获得小时值;
case命令;
case value in
val1) command
command;;
val2) command
command;;
esac
case语句中可以用特殊字符指定匹配模式,就和文件名替换中的一样:?、*、[...]
调试程序的-x选项;sh –x后面跟程序名及其参数;
把符合|用于两个模式之间时,其作用是逻辑或;如:
hour=$(date +%H)
case “$hour” in
0? | 1[01] ) echo “ morning”;;
1[2-7] ) echo “afternoon”;;
* ) echo “evening”;;
esac
空命令; :
&& 和 || 命令,和c类似;

循环

for命令格式:首先word1赋值给var,执行循环体,让后...
for var in word1 word2 ... wordn
do
command
...
done
shell允许在for命令的词列表中使用文件名替换;如:for file in file[1-4]、for file in *;
$@和$*类似,只是$@可以在前后加双引号;
for命令后面不带列表时;即 for var 等同于 for var in “$@”
while循环,先执行command1,并检测其退出状态,如果为0,就执行command;
while command1
do
command
...
done
while常与shift命令结合使用,以处理命令行中键入的参数个数可变的情况;
while [“$#” –ne 0 ]
do
echo “$1”
shift
done
until命令;格式同while,当command1退出状态为0时,循环结束;
发送邮件:echo “$user has loggde on” | mail fred
break命令同c的;且有break n;退出最里层的n重循环;
continue命令也同c的,且有continue n;使最里层的n重循环后面的所有命令都被跳过;
可以给循环重定向其输出输入,循环中的单个命令也可以再重定向;
终端:/dev/tty,它总表示你的终端;
如在单行或命令行中输入循环,格式如:for i in 1 2 3 4; do echo $i; done
其他循环及判断如上;
getcmd命令;
getopts命令;命令设计目标是在循环中运行,每次执行循环,getopts就检查一下命令行参数;同c的getopts;格式:getopts options variable;选项后面如果有:,则表示选项后面需要参数,并把该参数存入一个特殊的变量:OPTARG;每处理一次OPTIND会加1;

数据的读入和显示

read命令;
格式:read variables;shell从标准输入读入一行数据,并把读入的词一次赋给变量,如果读入的多,就把剩余的赋给最后一个变量;
echo命令会自动在其最后一个参数之后加上行结束符;
echo解释的医学特殊字符:/b 退格;/c 行尾不带行结束符;/f 换页;/n 换行;/r 回车;/t 制表符;等;
basename命令:给出参数的基本文件名;如 basename /usr/bin/file 得到file;
一个小拷贝程序:p204
numargs=$#
filelist=
copylist=
while [ “$#” –gt 1 ]
do
filelist=”$filelist $1”
shift
done
to=”$1”
if [“$numargs” –lt 2 –o “$numargs” –gt 2 –a ! –d “$to” ]
then
echo “Usage: mycp file1 file2”
echo “ mycp file(s) dir”
exit 1
fi
for from in $filelist
do
if [ -d “$to” ]
then
tofile=”$to/$(basename $from)”
else
tofile=”$to”
fi
if [ -e “$tofile” ]
then
echo “$tofile already exits; overwrite (yes/no) ? /c”
read answer
if [ “$answer” = yes ]
then
copylist=”$copylist $from”
fi
else
copylist=”$copylist $from”
fi
done
if [ -n “$copylist” ]
then
cp $copylist $to
fi
shell变量$$,保存当前进程的ID;
cat filename |
while read line
do
echo “$line”
done
上面通过管道把cat输出给while循环;
read命令-r选项,防止它解释反斜杠字符;
printf命令:格式:printf “format” arg1 arg2 ...
printf与echo不同,它不会自动向输出添加换行符;然而可以理解”/n”;

环境

子shell就是登陆shell为了运行期望的程序而执行的全新的shell;新shell运行时,是在自己是环境中运行,使用它自己的局部变量集;
局部变量
变量一旦被导出,对所有后续执行的子shell,该变量都是导出变量,包括孙子shell;语法:export variables;
导出变量的清单都复制给子shell;仅仅是复制;
export –p,就会得到shell所导出的所有变量的清单;
shell作为命令提示符显示的字符$存在变量PS1中,可以改变它;辅助命令提示符>存在于变量PS2中;
登陆系统后的宿主目录存在特殊变量:HOME中;当cd不带参数时,就使用该变量;
PATH指定是执行命令时shell要搜索的目录;这些目录彼此用冒号分隔;执行命令时也可以直接给命令指明路径;
CDPATH变量跟PATH变量相似;
.命令;读作”dot”;格式:. file;它的作用是在当前shell中执行file中的内容,也就是由当前shell来执行file中的命令,不产生子shell来执行这些程序;
一个应用,. mysql,如一个mysql中的内容:
HOME=/usr2/data
BIN=$HOME/bin
PATH=$PATH$BIN

PS1=”mysql> ”
export HOME BIN PATH PS1
/usr/bin/sh
exec命令:执行程序,格式 exec program;或重新分配标准输出输入,
格式 exec < file;exec > report;
可以把命令组成一组,用小括号或大括号括起来;小括号形式是用子shell执行这些命令;大括号则在当前shell中执行;且大括号的左括号后必须有个空格,最后一条命令后必须有分号;这样一组的命令可以使用&在后台进行执行;
给子shell传递变量的另一种方法,如DBHOME=/usr/data DBID=326 dbrun
同(DBHOME=/usr/data; DBID=326; export DBHOME DBID; dbrun)
profile文件;两个profile文件
在登录系统时,当shell显示命令提示符并等待你键入第一条命令时;在这之前,登录shell执行了系统中两个特殊文件:profile;一个是/etc/profile,该文件有系统管理员设置,通常做一些诸如检查是否有邮件、设置默认的创建文件的掩码、给某些标准导出变量赋值、以及任何管理员希望每当用户登录时都需要执行的命令;一个是宿主目录下面的.profile,当你得到账户时,系统给的一个默认文件,里面可以是一些环境变量,然后导出这些变量;
这两个文件是登陆shell执行的;(就如. /etc/profile . .profile)
一个关于终端的变量:TERM变量;
date命令和一些c标准库函数要用到TZ变量来确定时区信息;如:TZ=EST5 date

深入参数

参数替换
${parameter} 如因为参数名后面的字符可能会导致冲突,可以把参数名放在大括号中,如mv $file ${file}x
${parameter:-value};该结构意思:如果parameter不为空,就替换它的值,否则就替换为value;
${parameter:=value};当parameter为空时,不但使用value,还把它赋给parameter;但不能给位置参数赋值;这些不能作为单独的命令;
${parameter:?value};如果parameter不为空,shell就替换它的值;否则shell就把value写入标准错误,然后退出;
${parameter:+value};如果parameter不为空,则中结构替换为value;否则什么也不替换;
以上的value都可以是命令替换;如:WORKDIR=${DBDIR:-$(pwd)}
模式匹配结构:四种参数替换结构;每种结构都有两个参数:变量名以及模式;
${variable%pattern};shell在variable中查找,看它是否以给定的模式结尾,如果是就从命令行中把variable的内容从右边去掉最短的匹配模式;
${variable%%pattern};从右边去掉最长的匹配模式,不过只有在pattern中用了*时才是;人、否则同%;
${variable#pattern};从左边去掉;
${variable##pattern};从左边去掉最长的匹配pattern中的内容;
上面结构中都不对变量本身作修改;只有命令行中替换的内容受影响;
如检测存在file中的文件名是否以.o这两个字母结尾:if [ ${file%.o} != $file ]
$0变量:shell自动把程序名存在一个特殊的变量$0中;
set命令:设置各种shell选项,以及给位置参数$1、$2等重新赋值;
-x选项;打开shell的跟踪模式;set –x
+x选项;关闭跟踪模式;可以插入到程序里面;
命令行set a b c;把这些值赋给了$1、$2等,以及把个数赋给$#;
--选项;它让set不要把行中后面的其他字符作为选项;
IFS变量;代表内边字段分隔符;即空白字符;可以用:echo “$IFS” | od –b查看;可以给它赋值;
readonly命令用来说明以后不能修改其值的变量;变量的只读属性不能传递给子shell;且一旦为只读就没办法将它撤消;
readonly –p;得到只读变量的清单;
unset命令;把变量从环境中删除;但不能删除只读变量;

杂项

eval命令;eval command-line;shell在执行命令行之前扫描它两次;
如:pipe=”|”
eval ls $pipe wc -l
第一次扫描命令行时,它替换出pipe的值|,接着eval使它再次扫描命令行,这时shell把|作为管道符号了;
如:eval echo /$$#
wait命令;
wait process-id;process-id如为空,则shell等待所有的子进程完成;
$!变量保存shell最后一个送到后台的进程标志值;
trap命令;在按下删除键后,终端向运行中的程序发送信号,程序可以决定接受到信号后应该采取的行动,可以通过trap命令实现;trap commands signals;
常用信号编号:0 退出shell;1 挂起;2 中断(Delete、Ctrl+C);15 软件结束信号(kill发出);
如:trap “rm $WORKDIR/work1$$ $WORKDIR/dataout$$; exit” 1 2
trap “” 2;忽略信号,如果忽略一个信号,则所有的子shell也忽略该信号;如果设置一个信号的动作,而子shell还是采取默认动作;
trap 1 2;把收到信号1或2时的动作恢复为默认设置;
>&表示输出重定向到跟其后的文件描述符相关联的文件;
如标准输出和标准错误集中到一个文件:command > foo 2>>foo;或command >foo 2>&1
把标准输出定向到foo,把标准错误重定向到标准输出(因为它已经重定向到foo了)
>&-的作用是关闭标准输出,如果在前面加上文件描述符,就关闭与之关联的文件;<&-;
<<;内联输入重定向;如command <<word;格式把<<跟在命令之后,shell将把其后的各行作为command的标准输入,直到遇上仅包含word的行;如wc –l <<ENDOFDATA
shell对重定向的输入数据做参数替换、执行反引号中的命令并识别反斜杠字符。然而其他的特殊字符如*、|以及”等都忽略掉。如果在这些数据行中有美元符号、反引号、反斜杠字符,而且不希望shell来处理这些字符,可以在他们前面加上一个反斜杠字符;如果希望shell把所有的输入行都原样保留,可以在跟在<<之后的词之前加上反斜杠;如果紧接着<<的第一个字符是连字符-,shell就会把数据行中开头的制表符去掉;p274
内联输入重定向特性的最大用处之一是创建shell档案文件;
p378有个档案文件的例子不是很了解;
函数;格式:name(){ command; ... command; }
unset –f name;把一个函数的定义从shell中去掉;
函数中exit命令不只是结束函数,也结束调用函数的shell程序;
return命令只是结束函数;
type命令;如:type pwd;查看命令的来源,或类型;

!#;如果在一个文件中行首,那么该行余下的部分指明了对文件的一个解释;
ENV文件;当你启动shell时,它所做的第一件事情就是在你的环境中寻找名为ENV的变量,如果找到了,则执行由ENV所指定的文件;这非常类似于登陆时执行的配置文件;
行编辑器模式;set –o vi ;set –o emacs;打开vi模式或emacs模式;
命令历史记录列表保存在你的宿主目录下的文件.sh_history;
vi的一些命令:i、a是插入模式;esc后进入命令模式:w、b、x、h、l、$、0;k、j;/;
查看记录的命令:history,可以跟数字;
fc命令:可以为历史记录中的一条或多条命令启动编辑器,或直接将历史命令列在终端上;如:fc –l 100 122;将命令100到命令122写入标准输出;
fc –n –l -20;将最后20条命令写入标准输出;
alias命令;用例定义别名;如:alias name=string;alias ll=’ls –l’;unalias name;删除别名;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: