变量子目录

子目录  时间:2021-01-30  阅读:()

1)为何叫做shell在介绍shell是甚幺东西之前,不妨让我们重新检视使用者与计算机系统的关系:图(FIXME)我们知道计算机的运作不能离开硬件,但使用者却无法直接对硬件作驱动,硬件的驱动只能透过一个称为"操作系统(OperatingSystem)"的软件来控管,事实上,我们每天所谈的linux,严格来说只是一个操作系统,我们称之为"核心(kernel)".
然而,从使用者的角度来说,使用者也没办法直接操作kernel,而是透过kernel的"外壳"程序,也就是所谓的shell,来与kernel沟通.
这也正是kernel跟shell的形像命名关系.
如图:图(FIXME)从技术角度来说,shell是一个使用者与系统的互动界面(interface),主要是让使用者透过命令行(commandline)来使用系统以完成工作.
因此,shell的最简单的定义就是---命令解译器(CommandInterpreter):*将使用者的命令翻译给核心处理,*同时,将核心处理结果翻译给使用者.
每次当我们完成系统登入(login),我们就取得一个互动模式的shell,也称为loginshell或primaryshell.
若从行程(process)角度来说,我们在shell所下达的命令,均是shell所产生的子行程.
这现像,我们暂可称之为fork.
如果是执行脚本(shellscript)的话,脚本中的命令则是由另外一个非互动模式的子shell(subshell)来执行的.
也就是primaryshell产生subshell的行程,subshell再产生script中所有命令的行程.
(关于行程,我们日后有机会再补充.
)这里,我们必须知道:kernel与shell是不同的两套软件,而且都是可以被替换的:*不同的操作系统使用不同的kernel,*而在同一个kernel之上,也可使用不同的shell.
在linux的预设系统中,通常都可以找到好几种不同的shell,且通常会被列于如下档案里:/etc/shells不同的shell有着不同的功能,且也彼此各异、或说"大同小异".
常见的shell主要分为两大主流:sh:burneshell(sh)burneagainshell(bash)csh:cshell(csh)tcshell(tcsh)kornshell(ksh)(FIXME)大部份的Linux系统的预设shell都是bash,其原因大致如下两点:*自由软件*功能强大bash是gnuproject最成功的产品之一,自推出以来深受广大Unix用户喜爱,且也逐渐成为不少组织的系统标准.
2)shellprompt(PS1)与CarriageReturn(CR)的关系当你成功登录进一个文字界面之后,大部份情形下,你会在荧幕上看到一个不断闪烁的方块或底线(视不同版本而别),我们称之为*游标*(coursor).
游标的作用就是告诉你接下来你从键盘输入的按键所插入的位置,且每输如一键游标便向右边移动一个格子,若连续输入太多的话,则自动接在下一行输入.

假如你刚完成登录还没输入任何按键之前,你所看到的游标所在位置的同一行的左边部份,我们称之为*提示符号*(prompt).
提示符号的格式或因不同系统版本而各有不同,在Linux上,只需留意最接近游标的一个可见的提示符号,通常是如下两者之一:$:给一般使用者帐号使用#:给root(管理员)帐号使用事实上,shellprompt的意思很简单:*是shell告诉使用者:您现在可以输入命令行了.
我们可以说,使用者只有在得到shellprompt才能打命令行,而cursor是指示键盘在命令行所输入的位置,使用者每输入一个键,cursor就往后移动一格,直到碰到命令行读进CR(CarriageReturn,由Enter键产生)字符为止.
CR的意思也很简单:*是使用者告诉shell:老兄你可以执行我的命令行了.
严格来说:*所谓的命令行,就是在shellprompt与CR字符之间所输入的文字.
(思考:为何我们这里坚持使用CR字符而不说Enter键呢答案在后面的学习中揭晓.
)不同的命令可接受的命令行格式或有不同,一般情况下,一个标准的命令行格式为如下所列:command-nameoptionsargument若从技术细节来看,shell会依据IFS(InternalFieldSeperator)将commandline所输入的文字给拆解为"字段"(word).
然后再针对特殊字符(meta)先作处理,最后再重组整行commandline.
(注意:请务必理解上两句话的意思,我们日后的学习中会常回到这里思考.
)其中的IFS是shell预设使用的字段分隔符,可以由一个及多个如下按键组成:*空格键(WhiteSpace)*表格键(Tab)*回车键(Enter)系统可接受的命令名称(command-name)可以从如下途径获得:*明确路径所指定的外部命令*命令别名(alias)*自定功能(function)*shell内建命令(built-in)*$PATH之下的外部命令每一个命令行均必需含用命令名称,这是不能缺少的.
3)别人echo、你也echo,是问echo知多少承接上一章所介绍的commandline,这里我们用echo这个命令加以进一步说明.
温习---标准的commandline包含三个部件:*command_nameoptionargumentecho是一个非常简单、直接的Linux命令:*将argument送出至标准输出(STDOUT),通常就是在监视器(monitor)上输出.
(注:stdout我们日后有机会再解说,或可先参考如下讨论:http://www.
chinaunix.
net/forum/viewtopic.
phpt=191375)为了更好理解,不如先让我们先跑一下echo命令好了:代码:$echo$你会发现只有一个空白行,然后又回到shellprompt上了.
这是因为echo在预设上,在显示完argument之后,还会送出一个换行符号(new-linecharactor).
但是上面的command并没任何的argument,那结果就只剩一个换行符号了.
.
.
若你要取消这个换行符号,可利用echo的-noption:代码:$echo-n$不妨让我们回到commandline的概念上来讨论上例的echo命令好了:*commandline只有command_name(echo)及option(-n),并没有任何argument.
要想看看echo的argument,那还不简单﹗接下来,你可试试如下的输入:代码:$echofirstlinefirstline$echo-nfirstlinefirstline$于上两个echo命令中,你会发现argument的部份显示在你的荧幕,而换行符号则视-noption的有无而别.
很明显的,第二个echo由于换行符号被取消了,接下来的shellprompt就接在输出结果同一行了.
.
.
^_^事实上,echo除了-noptions之外,常用选项还有:-e:启用反斜线控制字符的转换(参考下表)-E:关闭反斜线控制字符的转换(预设如此)-n:取消行末之换行符号(与-e选项下的\c字符同意)关于echo命令所支持的反斜线控制字符如下表:\a:ALERT/BELL(从系统喇叭送出铃声)\b:BACKSPACE,也就是向左删除键\c:取消行末之换行符号\E:ESCAPE,跳脱键\f:FORMFEED,换页字符\n:NEWLINE,换行字符\r:RETURN,回车键\t:TAB,表格跳位键\v:VERTICALTAB,垂直表格跳位键\n:ASCII八进位编码(以x开首为十六进制)\\:反斜线本身(表格资料来自O'Reilly出版社之LearningtheBashShell,2ndEd.
)或许,我们可以透过实例来了解echo的选项及控制字符:例一:代码:$echo-e"a\tb\tc\nd\te\tf"abcdef上例运用\t来区隔abc还有def,及用\n将def换至下一行.
例二:代码:$echo-e"\141\011\142\011\143\012\144\011\145\011\146"abcdef与例一的结果一样,只是使用ASCII八进位编码.
例三:代码:$echo-e"\x61\x09\x62\x09\x63\x0a\x64\x09\x65\x09\x66"abcdef与例二差不多,只是这次换用ASCII十六进制编码.
例四:代码:$echo-ne"a\tb\tc\nd\te\bf\a"abcdf$因为e字母后面是删除键(\b),因此输出结果就没有e了.
在结束时听到一声铃向,那是\a的杰作﹗由于同时使用了-n选项,因此shellprompt紧接在第二行之后.
若你不用-n的话,那你在\a后再加个\c,也是同样的效果.
事实上,在日后的shell操作及shellscript设计上,echo命令是最常被使用的命令之一.
比方说,用echo来检查变量值:代码:$A=B$echo$AB$echo$0(注:关于变量概念,我们留到下两章才跟大家说明.
)好了,更多的关于commandline的格式,以及echo命令的选项,就请您自行多加练习、运用了.
.
.
4)""(双引号)与''(单引号)差在哪还是回到我们的commandline来吧.
.
.
经过前面两章的学习,应该很清楚当你在shellprompt后面敲打键盘、直到按下Enter的时候,你输入的文字就是commandline了,然后shell才会以行程的方式执行你所交给它的命令.
但是,你又可知道:你在commandline输入的每一个文字,对shell来说,是有类别之分的呢简单而言(我不敢说这是精确的定议,注一),commandline的每一个charactor,分为如下两种:*literal:也就是普通纯文字,对shell来说没特殊功能.
*meta:对shell来说,具有特定功能的特殊保留字符.
(注一:关于bashshell在处理commandline时的顺序说明,请参考O'Reilly出版社之LearningtheBashShell,2ndEdition,第177-180页的说明,尤其是178页的流程图Figure7-1.
.
.
)Literal没甚么好谈的,凡举abcd、123456这些"文字"都是literal.
.
.
(easy)但meta却常使我们困惑.
.
.
.
.
(confused)事实上,前两章我们在commandline中已碰到两个机乎每次都会碰到的meta:*IFS:由或或三者之一组成(我们常用space).
*CR:由产生.
IFS是用来拆解commandline的每一个词(word)用的,因为shellcommandline是按词来处理的.
而CR则是用来结束commandline用的,这也是为何我们敲命令就会跑的原因.
除了IFS与CR,常用的meta还有:=:设定变量.
$:作变量或运算替换(请不要与shellprompt搞混了).
>:重导向stdout.
,再执行C命令在第二次设定A变量时,由于空格键被置于softquote中,因此被关闭,不再作为IFS:*A=BC事实上,空格键无论在softquote还是在hardquote中,均会被关闭.
Enter键亦然:代码:$A='B>C>'$echo"$A"BC在上例中,由于被置于hardquote当中,因此不再作为CR字符来处理.
这里的单纯只是一个断行符号(new-line)而已,由于commandline并没得到CR字符,因此进入第二个shellprompt(PS2,以>符号表示),commandline并不会结束,直到第三行,我们输入的并不在hardquote里面,因此并没被关闭,此时,commandline碰到CR字符,于是结束、交给shell来处理.
上例的要是被置于softquote中的话,CR也会同样被关闭:代码:$A="B>C>"$echo$ABC然而,由于echo$A时的变量没至于softquote中,因此当变量替换完成后并作命令行重组时,会被解释为IFS,而不是解释为NewLine字符.
同样的,用escape亦可关闭CR字符:代码:$A=B\>C\>$echo$ABC上例中,第一个跟第二个均被escape字符关闭了,因此也不作为CR来处理,但第三个由于没被跳脱,因此作为CR结束commandline.
但由于键本身在shellmeta中的特殊性,在\跳脱后面,仅仅取消其CR功能,而不会保留其IFS功能.
您或许发现光是一个键所产生的字符就有可能是如下这些可能:CRIFSNL(NewLine)FF(FormFeed)NULL.
.
.
至于甚么时候会解释为甚么字符,这个我就没去深挖了,或是留给读者诸君自行慢慢摸索了.
.
.

^_^至于softquote跟hardquote的不同,主要是对于某些meta的关闭与否,以$来作说明:代码:$A=B\C$echo"$A"BC$echo'$A'$A在第一个echo命令行中,$被置于softquote中,将不被关闭,因此继续处理变量替换,因此echo将A的变量值输出到荧幕,也就得到"BC"的结果.
在第二个echo命令行中,$被置于hardquote中,则被关闭,因此$只是一个$符号,并不会用来作变量替换处理,因此结果是$符号后面接一个A字母:$A.
练习与思考:如下结果为何不同代码:$A=B\C$echo'"$A"'#最外面的是单引号"$A"$echo"'$A'"#最外面的是双引号'BC'(提示:单引号及双引号,在quoting中均被关#93;了.
)在CU的shell版里,我发现有很多初学者的问题,都与quoting理解的有关.
比方说,若我们在awk或sed的命令参数中调用之前设定的一些变量时,常会问及为何不能的问题.
要解决这些问题,关键点就是:*区分出shellmeta与commandmeta前面我们提到的那些meta,都是在commandline中有特殊用途的,比方说{}是将其内一系列commandline置于不具名的函式中执行(可简单视为commandblock),但是,awk却需要用{}来区分出awk的命令区段(BEGIN,MAIN,END).
若你在commandline中如此输入:代码:$awk{print$0}1.
txt由于{}在shell中并没关闭,那shell就将{print$0}视为commandblock,但同时又没有";"符号作命令区隔,因此就出现awk的语法错误结果.
要解决之,可用hardquote:代码:$awk'{print$0}'1.
txt上面的hardquote应好理解,就是将原本的{、、$(注三)、}这几个shellmeta关闭,避免掉在shell中遭到处理,而完整的成为awk参数中的commandmeta.
(注三:而其中的$0是awk内建的fieldnumber,而非awk的变量,awk自身的变量无需使用$.
)要是理解了hardquote的功能,再来理解softquote与escape就不难:代码:awk"{print\$0}"1.
txtawk\{print\\$0\}1.
txt然而,若你要改变awk的$0的0值是从另一个shell变量读进呢比方说:已有变量$A的值是0,那如何在commandline中解决awk的$$A呢你可以很直接否定掉hardquoe的方案:代码:$awk'{print$$A}'1.
txt那是因为$A的$在hardquote中是不能替换变量的.
聪明的读者(如你!
),经过本章学习,我想,应该可以解释为何我们可以使用如下操作了吧:代码:A=0awk"{print\$$A}"1.
txtawk\{print\\$$A\}1.
txtawk'{print$'$A'}'1.
txtawk'{print$'"$A"'}'1.
txt#注:"$A"包在softquote中或许,你能举出更多的方案呢.
.
.
.
^_^练习与思考:请运用本章学到的知识分析如下两串讨论:http://bbs.
chinaunix.
net/forum/viewtopic.
phpt=207178http://bbs.
chinaunix.
net/forum/viewtopic.
phpt=2167295)var=valueexport前后差在哪这次让我们暂时丢开commandline,先来了解一下bash变量(variable)吧.
.
.
所谓的变量,就是就是利用一个特定的"名称"(name)来存取一段可以变化的"值"(value).

*设定(set)*在bash中,你可以用"="来设定或重新定义变量的内容:name=value在设定变量的时侯,得遵守如下规则:*等号左右两边不能使用区隔符号(IFS),也应避免使用shell的保留字符(metacharactor).
*变量名称不能使用$符号.
*变量名称的第一个字母不能是数字(number).
*变量名称长度不可超过256个字母.
*变量名称及变量值之大小写是有区别的(casesensitive).
如下是一些变量设定时常见的错误:A=B:不能有IFS1A=B:不能以数字开头$A=B:名称不能有$a=B:这跟a=b是不同的如下则是可以接受的设定:A="B":IFS被关闭了(请参考前面的quoting章节)A1=B:并非以数字开头A=$B:$可用在变量值内This_Is_A_Long_Name=b:可用_连接较长的名称或值,且大小写有别.
*变量替换(substitution)*Shell之所以强大,其中的一个因素是它可以在命令行中对变量作替换(substitution)处理.

在命令行中使用者可以使用$符号加上变量名称(除了在用=号定义变量名称之外),将变量值给替换出来,然后再重新组建命令行.
比方:代码:$A=ls$B=la$C=/tmp$$A-$B$C(注意:以上命令行的第一个$是shellprompt,并不在命令行之内.
)必需强调的是,我们所提的变量替换,只发生在commandline上面.
(是的,让我们再回到commandline吧﹗)仔细分析最后那行commandline,不难发现在被执行之前(在输入CR字符之前),$符号会对每一个变量作替换处理(将变量值替换出来再重组命令行),最后会得出如下命令行:代码:ls-la/tmp还记得第二章我请大家"务必理解"的那两句吗若你忘了,那我这里再重贴一遍:引用:若从技术细节来看,shell会依据IFS(InternalFieldSeperator)将commandline所输入的文字给拆解为"字段"(word).
然后再针对特殊字符(meta)先作处理,最后再重组整行commandline.
这里的$就是commandline中最经典的meta之一了,就是作变量替换的﹗在日常的shell操作中,我们常会使用echo命令来查看特定变量的值,例如:代码:$echo$A-$B$C我们已学过,echo命令只单纯将其argument送至"标准输出"(STDOUT,通常是我们的荧幕).
所以上面的命令会在荧幕上得到如下结果:代码:ls-la/tmp这是由于echo命令在执行时,会先将$A(ls)、$B(la)、跟$C(/tmp)给替换出来的结果.
利用shell对变量的替换处理能力,我们在设定变量时就更为灵活了:A=BB=$A这样,B的变量值就可继承A变量"当时"的变量值了.
不过,不要以"数学罗辑"来套用变量的设定,比方说:A=BB=C这样并不会让A的变量值变成C.
再如:A=BB=$AA=C同样也不会让B的值换成C.
上面是单纯定义了两个不同名称的变量:A与B,它们的值分别是B与C.
若变量被重复定义的话,则原有旧值将被新值所取代.
(这不正是"可变的量"吗^_^)当我们在设定变量的时侯,请记着这点:*用一个名称储存一个数值仅此而已.
此外,我们也可利用命令行的变量替换能力来"扩充"(append)变量值:A=B:C:DA=$A:E这样,第一行我们设定A的值为"B:C:D",然后,第二行再将值扩充为"A:B:C:E".
上面的扩充范例,我们使用区隔符号(:)来达到扩充目的,要是没有区隔符号的话,如下是有问题的:A=BCDA=$AE因为第二次是将A的值继承$AE的提换结果,而非$A再加E﹗要解决此问题,我们可用更严谨的替换处理:A=BCDA=${A}E上例中,我们使用{}将变量名称的范围给明确定义出来,如此一来,我们就可以将A的变量值从BCD给扩充为BCDE.
(提示:关于${name}事实上还可做到更多的变量处理能力,这些均属于比较进阶的变量处理,现阶段暂时不介绍了,请大家自行参考资料.
如CU的贴子:http://www.
chinaunix.
net/forum/viewtopic.
phpt=201843)*export*严格来说,我们在当前shell中所定义的变量,均属于"本地变量"(localvariable),只有经过export命令的"输出"处理,才能成为环境变量(environmentvariable):代码:$A=B$exportA或:代码:$exportA=B经过export输出处理之后,变量A就能成为一个环境变量供其后的命令使用.
在使用export的时侯,请别忘记shell在命令行对变量的"替换"(substitution)处理,比方说:代码:$A=B$B=C$export$A上面的命令并未将A输出为环境变量,而是将B作输出,这是因为在这个命令行中,$A会首先被提换出B然后再"塞回"作export的参数.
要理解这个export,事实上需要从process的角度来理解才能透彻.
我将于下一章为大家说明process的观念,敬请留意.
*取消变量*要取消一个变量,在bash中可使用unset命令来处理:代码:unsetA与export一样,unset命令行也同样会作变量替换(这其实就是shell的功能之一),因此:代码:$A=B$B=C$unset$A事实上所取消的变量是B而不是A.
此外,变量一旦经过unset取消之后,其结果是将整个变量拿掉,而不仅是取消其变量值.
如下两行其实是很不一样的:代码:$A=$unsetA第一行只是将变量A设定为"空值"(nullvalue),但第二行则让变量A不在存在.
虽然用眼睛来看,这两种变量状态在如下命令结果中都是一样的:代码:$A=$echo$A$unsetA$echo$A请学员务必能识别nullvalue与unset的本质区别,这在一些进阶的变量处理上是很严格的.
比方说:代码:$str=#设为null$var=${str=expr}#定义var$echo$var$echo$str$unsetstr#取消$var=${str=expr}#定义var$echo$varexpr$echo$strexpr聪明的读者(yes,you!
),稍加思考的话,应该不难发现为何同样的var=${str=expr}在null与unset之下的不同吧若你看不出来,那可能是如下原因之一:a.
你太笨了b.
不了解var=${str=expr}这个进阶处理c.
对本篇说明还没来得及消化吸收e.
我讲得不好不知,你选哪个呢6)exec跟source差在哪这次先让我们从CUShell版的一个实例贴子来谈起吧:(http://www.
chinaunix.
net/forum/viewtopic.
phpt=194191)例中的提问是:引用:cd/etc/aa/bb/cc可以执行但是把这条命令写入shell时shell不执行!
这是什幺原因呀!
我当时如何回答暂时别去深究,先让我们了解一下行程(process)的观念好了.

首先,我们所执行的任何程序,都是由父行程(parentprocess)所产生出来的一个子行程(childprocess),子行程在结束后,将返回到父行程去.
此一现像在Linux系统中被称为fork.
(为何要程为fork呢嗯,画一下图或许比较好理解.
当子行程被产生的时候,将会从父行程那里获得一定的资源分配、及(更重要的是)继承父行程的环境﹗让我们回到上一章所谈到的"环境变量"吧:*所谓环境变量其实就是那些会传给子行程的变量.
简单而言,"遗传性"就是区分本地变量与环境变量的决定性指针.
然而,从遗传的角度来看,我们也不难发现环境变量的另一个重要特征:*环境变量只能从父行程到子行程单向继承.
换句话说:在子行程中的环境如何变更,均不会影响父行程的环境.
接下来,再让我们了解一下命令脚本(shellscript)的概念.
所谓的shellscript讲起来很简单,就是将你平时在shellprompt后所输入的多行commandline依序写入一个文件去而已.
其中再加上一些条件判断、互动界面、参数运用、函数调用、等等技巧,得以让script更加"聪明"的执行,但若撇开这些技巧不谈,我们真的可以简单的看成script只不过依次执行预先写好的命令行而已.
再结合以上两个概念(process+script),那应该就不难理解如下这句话的意思了:*正常来说,当我们执行一个shellscript时,其实是先产生一个sub-shell的子行程,然后sub-shell再去产生命令行的子行程.
然则,那让我们回到本章开始时所提到的例子再从新思考:引用:cd/etc/aa/bb/cc可以执行但是把这条命令写入shell时shell不执行!
这是什幺原因呀!
我当时的答案是这样的:引用:因为,一般我们跑的shellscript是用subshell去执行的.
从process的观念来看,是parentprocess产生一个childprocess去执行,当child结束后,会返回parent,但parent的环境是不会因child的改变而改变的.
所谓的环境元数很多,凡举effectiveid,variable,workdingdir等等.
.
.
其中的workdingdir($PWD)正是楼主的疑问所在:当用subshell来跑script的话,subshell的$PWD会因为cd而变更,但当返回primaryshell时,$PWD是不会变更的.
能够了解问题的原因及其原理是很好的,但是如何解决问题恐怕是我们更感兴趣的﹗是吧^_^那好,接下来,再让我们了解一下source命令好了.
当你有了fork的概念之后,要理解source就不难:*所谓source就是让script在当前shell内执行、而不是产生一个sub-shell来执行.
由于所有执行结果均于当前shell内完成,若script的环境有所改变,当然也会改变当前环境了﹗因此,只要我们要将原本单独输入的script命令行变成source命令的参数,就可轻易解决前例提到的问题了.
比方说,原本我们是如此执行script的:代码:.
/my.
script现在改成这样即可:代码:source.
/my.
script或:.
.
/my.
script说到这里,我想,各位有兴趣看看/etc底下的众多设定文件,应该不难理解它们被定议后,如何让其它script读取并继承了吧若然,日后你有机会写自己的script,应也不难专门指定一个设定文件以供不同的script一起"共享"了.
.
.
^_^okay,到这里,若你搞得懂fork与source的不同,那接下来再接受一个挑战:----那exec又与source/fork有何不同呢哦.
.
.
要了解exec或许较为复杂,尤其扯上FileDescriptor的话.
.
.
不过,简单来说:*exec也是让script在同一个行程上执行,但是原有行程则被结束了.
也就是简而言之:原有行程会否终止,就是exec与source/fork的最大差异了.
嗯,光是从理论去理解,或许没那么好消化,不如动手"实作+思考"来的印像深刻哦.

下面让我们写两个简单的script,分别命令为1.
sh及2.
sh:1.
sh代码:#!
/bin/bashA=Becho"PIDfor1.
shbeforeexec/source/fork:$$"exportAecho"1.
sh:\$Ais$A"case$1inexec)echo"usingexec.
.
.
"exec.
/2.
sh;;source)echo"usingsource.
.
.
".
.
/2.
sh;;*)echo"usingforkbydefault.
.
.
".
/2.
sh;;esacecho"PIDfor1.
shafterexec/source/fork:$$"echo"1.
sh:\$Ais$A"2.
sh代码:#!
/bin/bashecho"PIDfor2.
sh:$$"echo"2.
shget\$A=$Afrom1.
sh"A=CexportAecho"2.
sh:\$Ais$A"然后,分别跑如下参数来观察结果:代码:$.
/1.
shfork$.
/1.
shsource$.
/1.
shexec或是,你也可以参考CU上的另一贴子:http://www.
chinaunix.
net/forum/viewtopic.
phpt=191051好了,别忘了仔细比较输出结果的不同及背后的原因哦.
.
.
若有疑问,欢迎提出来一起讨论讨论~~~happyscripting!
^_^7)()与{}差在哪嗯,这次轻松一下,不讲太多.
.
.
^_^先说一下,为何要用()或{}好了.
许多时候,我们在shell操作上,需要在一定条件下一次执行多个命令,也就是说,要么不执行,要么就全执行,而不是每次依序的判断是否要执行下一个命令.

或是,需要从一些命令执行优先次顺中得到豁免,如算术的2*(3+4)那样.
.
.
这时候,我们就可引入"命令群组"(commandgroup)的概念:将多个命令集中处理.
在shellcommandline中,一般人或许不太计较()与{}这两对符号的差异,虽然两者都可将多个命令作群组化处理,但若从技术细节上,却是很不一样的:()将commandgroup置于sub-shell去执行,也称nestedsub-shell.
{}则是在同一个shell内完成,也称为non-namedcommandgroup.
若,你对上一章的fork与source的概念还记得了的话,那就不难理解两者的差异了.
要是在commandgroup中扯上变量及其它环境的修改,我们可以根据不同的需求来使用()或{}.
通常而言,若所作的修改是临时的,且不想影响原有或以后的设定,那我们就nestedsub-shell,反之,则用non-namedcommandgroup.
是的,光从commandline来看,()与{}的差别就讲完了,够轻松吧~~~^_^然而,若这两个meta用在其它commandmeta或领域中(如RegularExpression),还是有很多差别的.
只是,我不打算再去说明了,留给读者自己慢慢发掘好了.
.
.
我这里只想补充一个概念,就是function.
所谓的function,就是用一个名字去命名一个commandgroup,然后再调用这个名字去执行commandgroup.
从non-namedcommandgroup来推断,大概你也可以猜到我要说的是{}了吧(yes!
你真聪明﹗^_^)在bash中,function的定义方式有两种:方式一:代码:functionfunction_name{command1command2command3.
.
.
.
}方式二:代码:fuction_name(){command1command2command3.
.
.
.
}用哪一种方式无所谓,只是若碰到所定意的名称与现有的命令或别名(Alias)冲突的话,方式二或许会失败.
但方式二起码可以少打function这一串英文字母,对懒人来说(如我),又何乐不为呢.
.
.
^_^function在某一程度来说,也可称为"函式",但请不要与传统编程所使用的函式(library)搞混了,毕竟两者差异很大.
惟一相同的是,我们都可以随时用"已定义的名称"来调用它们.
.
.
若我们在shell操作中,需要不断的重复质行某些命令,我们首先想到的,或许是将命令写成命令稿(shellscript).
不过,我们也可以写成function,然后在commandline中打上function_name就可当一舨的script来使用了.
只是若你在shell中定义的function,除了可用unsetfunction_name取消外,一旦退出shell,function也跟着取消.
然而,在script中使用function却有许多好处,除了可以提高整体script的执行效能外(因为已被加载),还可以节省许多重复的代码.
.
.
简单而言,若你会将多个命令写成script以供调用的话,那,你可以将function看成是script中的script.
.
.
^_^而且,透过上一章介绍的source命令,我们可以自行定义许许多多好用的function,再集中写在特定文件中,然后,在其它的script中用source将它们加载并反复执行.
若你是RedHatLinux的使用者,或许,已经猜得出/etc/rc.
d/init.
d/functions这个文件是作啥用的了~~~^_^okay,说要轻松点的嘛,那这次就暂时写到这吧.
祝大家学习愉快﹗^_^8)与$()还有${}差在哪我们上一章介绍了()与{}的不同,这次让我们扩展一下,看看更多的变化:$()与${}又是啥玩意儿呢在bashshell中,$()与``(反引号)都是用来做命令替换用(commandsubstitution)的.
所谓的命令替换与我们第五章学过的变量替换差不多,都是用来重组命令行:*完成引号里的命令行,然后将其结果替换出来,再重组命令行.
例如:代码:$echothelastsundayis$(date-d"lastsunday"+%Y-%m-%d)如此便可方便得到上一星期天的日期了.
.
.
^_^在操作上,用$()或``都无所谓,只是我"个人"比较喜欢用$(),理由是:1,``很容易与''(单引号)搞混乱,尤其对初学者来说.
有时在一些奇怪的字形显示中,两种符号是一模一样的(直竖两点).
当然了,有经验的朋友还是一眼就能分辩两者.
只是,若能更好的避免混乱,又何乐不为呢^_^2,在多层次的复合替换中,``须要额外的跳脱(\`)处理,而$()则比较直观.
例如:这是错的:代码:command1`command2`command3``原本的意图是要在command2`command3`先将command3提换出来给command2处理,然后再将结果传给command1`command2.
.
.
`来处理.
然而,真正的结果在命令行中却是分成了`command2`与``两段.
正确的输入应该如下:代码:command1`command2\`command3\``要不然,换成$()就没问题了:代码:command1$(command2$(command3))只要你喜欢,做多少层的替换都没问题啦~~~^_^不过,$()并不是没有毙端的.
.
.
首先,``基本上可用在全部的unixshell中使用,若写成shellscript,其移植性比较高.
而$()并不见的每一种shell都能使用,我只能跟你说,若你用bash2的话,肯定没问题.
.
.
^_^接下来,再让我们看${}吧.
.
.
它其实就是用来作变量替换用的啦.
一般情况下,$var与${var}并没有啥不一样.
但是用${}会比较精确的界定变量名称的范围,比方说:代码:$A=B$echo$AB原本是打算先将$A的结果替换出来,然后再补一个B字母于其后,但在命令行上,真正的结果却是只会提换变量名称为AB的值出来.
.
.
若使用${}就没问题了:代码:$echo${A}BBB不过,假如你只看到${}只能用来界定变量名称的话,那你就实在太小看bash了﹗有兴趣的话,你可先参考一下cu本版的精华文章:http://www.
chinaunix.
net/forum/viewtopic.
phpt=201843为了完整起见,我这里再用一些例子加以说明${}的一些特异功能:假设我们定义了一个变量为:file=/dir1/dir2/dir3/my.
file.
txt我们可以用${}分别替换获得不同的值:${file#*/}:拿掉第一条/及其左边的字符串:dir1/dir2/dir3/my.
file.
txt${file##*/}:拿掉最后一条/及其左边的字符串:my.
file.
txt${file#*.
}:拿掉第一个.
及其左边的字符串:file.
txt${file##*.
}:拿掉最后一个.
及其左边的字符串:txt${file%/*}:拿掉最后条/及其右边的字符串:/dir1/dir2/dir3${file%%/*}:拿掉第一条/及其右边的字符串:(空值)${file%.
*}:拿掉最后一个.
及其右边的字符串:/dir1/dir2/dir3/my.
file${file%%.
*}:拿掉第一个.
及其右边的字符串:/dir1/dir2/dir3/my记忆的方法为:#是去掉左边(在鉴盘上#在$之左边)%是去掉右边(在鉴盘上%在$之右边)单一符号是最小匹配﹔两个符号是最大匹配.
${file:0:5}:提取最左边的5个字节:/dir1${file:5:5}:提取第5个字节右边的连续5个字节:/dir2我们也可以对变量值里的字符串作替换:${file/dir/path}:将第一个dir提换为path:/path1/dir2/dir3/my.
file.
txt${file//dir/path}:将全部dir提换为path:/path1/path2/path3/my.
file.
txt利用${}还可针对不同的变量状态赋值(没设定、空值、非空值):${file-my.
file.
txt}:假如$file没有设定,则使用my.
file.
txt作传回值.
(空值及非空值时不作处理)${file:-my.
file.
txt}:假如$file没有设定或为空值,则使用my.
file.
txt作传回值.
(非空值时不作处理)${file+my.
file.
txt}:不管$file为何值,均使用my.
file.
txt作传回值.
${file:+my.
file.
txt}:若$file为非空值,则使用my.
file.
txt作传回值.
(没设定及空值时不作处理)${file=my.
file.
txt}:若$file没设定,则使用my.
file.
txt作传回值,同时将$file赋值为my.
file.
txt.
(空值及非空值时不作处理)${file:=my.
file.
txt}:若$file没设定或为空值,则使用my.
file.
txt作传回值,同时将$file赋值为my.
file.
txt.
(非空值时不作处理)${filemy.
file.
txt}:若$file没设定,则将my.
file.
txt输出至STDERR.
(空值及非空值时不作处理)${file:my.
file.
txt}:若$file没设定或为空值,则将my.
file.
txt输出至STDERR.
(非空值时不作处理)还有哦,${#var}可计算出变量值的长度:${#file}可得到27,因为/dir1/dir2/dir3/my.
file.
txt刚好是27个字节.
.
.
接下来,再为大家介稍一下bash的组数(array)处理方法.
一般而言,A="abcdef"这样的变量只是将$A替换为一个单一的字符串,但是改为A=(abcdef),则是将$A定义为组数.
.
.
bash的组数替换方法可参考如下方法:${A[@]}或${A[*]}可得到abcdef(全部组数)${A[0]}可得到a(第一个组数),${A[1]}则为第二个组数.
.
.
${#A[@]}或${#A[*]}可得到4(全部组数数量)${#A[0]}可得到1(即第一个组数(a)的长度),${#A[3]}可得到3(第四个组数(def)的长度)A[3]=xyz则是将第四个组数重新定义为xyz.
.
.
诸如此类的.
.
.
.
能够善用bash的$()与${}可大大提高及简化shell在变量上的处理能力哦~~~^_^好了,最后为大家介绍$(())的用途吧:它是用来作整数运算的.
在bash中,$(())的整数运算符号大致有这些:分别为"加、减、乘、除".
%:余数运算&|^!
:分别为"AND、OR、XOR、NOT"运算.
例:代码:$a=5;b=7;c=2$echo$((a+b*c))19$echo$(((a+b)/c))6$echo$(((a*b)%c))1在$(())中的变量名称,可于其前面加$符号来替换,也可以不用,如:$(($a+$b*$c))也可得到19的结果此外,$(())还可作不同进位(如二进制、八进位、十六进制)作运算呢,只是,输出结果皆为十进制而已:echo$((16#2a))结果为42(16进位转十进制)以一个实用的例子来看看吧:假如当前的umask是022,那么新建文件的权限即为:代码:$umask022$echo"obase=8;$((8#666&(8#777^8#$(umask)bc644事实上,单纯用(())也可重定义变量值,或作testing:a=5;((a++))可将$a重定义为6a=5;((a--))则为a=4a=5;b=7;((a:大于=:大于或等于==:等于!
=:不等于不过,使用(())作整数测试时,请不要跟[]的整数测试搞混乱了.
(更多的测试我将于第十章为大家介绍)怎样好玩吧.
.
^_^okay,这次暂时说这么多.
.
.
上面的介绍,并没有详列每一种可用的状态,更多的,就请读者参考手册文件啰.
.
.

9)$@与$*差在哪要说$@与$*之前,需得先从shellscript的positionalparameter谈起.
.
.
我们都已经知道变量(variable)是如何定义及替换的,这个不用再多讲了.
但是,我们还需要知道有些变量是shell内定的,且其名称是我们不能随意修改的,其中就有positionalparameter在内.
在shellscript中,我们可用$0,$1,$2,$3.
.
.
这样的变量分别提取命令行中的如下部份:代码:script_nameparameter1parameter2parameter3.
.
.
我们很容易就能猜出$0就是代表shellscript名称(路径)本身,而$1就是其后的第一个参数,如此类推.
.
.
.
须得留意的是IFS的作用,也就是,若IFS被quoting处理后,那么positionalparameter也会改变.
如下例:代码:my.
shp1"p2p3"p4由于在p2与p3之间的空格键被softquote所关闭了,因此my.
sh中的$2是"p2p3"而$3则是p4.
.
.
还记得前两章我们提到fucntion时,我不是说过它是script中的script吗^_^是的,function一样可以读取自己的(有别于script的)postitionalparameter,惟一例外的是$0而已.
举例而言:假设my.
sh里有一个fucntion叫my_fun,若在script中跑my_funfp1fp2fp3,那么,function内的$0是my.
sh,而$1则是fp1而非p1了.
.
.
不如写个简单的my.
shscript看看吧:代码:#!
/bin/bashmy_fun(){echo'$0insidefunctionis'$0echo'$1insidefunctionis'$1echo'$2insidefunctionis'$2}echo'$0outsidefunctionis'$0echo'$1outsidefunctionis'$1echo'$2outsidefunctionis'$2my_funfp1"fp2fp3"然后在commandline中跑一下script就知道了:代码:chmod+xmy.
sh.
/my.
shp1"p2p3"$0outsidefunctionis.
/my.
sh$1outsidefunctionisp1$2outsidefunctionisp2p3$0insidefunctionis.
/my.
sh$1insidefunctionisfp1$2insidefunctionisfp2fp3然而,在使用positionalparameter的时候,我们要注意一些陷阱哦:*$10不是替换第10个参数,而是替换第一个参数($1)然后再补一个0于其后﹗也就是,my.
shonetwothreefourfivesixseveneigthnineten这样的commandline,my.
sh里的$10不是ten而是one0哦.
.
.
小心小心﹗要抓到ten的话,有两种方法:方法一是使用我们上一章介绍的${},也就是用${10}即可.
方法二,就是shift了.
用通俗的说法来说,所谓的shift就是取消positionalparameter中最左边的参数($0不受影响).
其默认值为1,也就是shift或shift1都是取消$1,而原本的$2则变成$1、$3变成$2.
.
.
若shift3则是取消前面三个参数,也就是原本的$4将变成$1.
.
.
那,亲爱的读者,你说要shift掉多少个参数,才可用$1取得${10}呢^_^okay,当我们对positionalparameter有了基本概念之后,那再让我们看看其它相关变量吧.
首先是$#:它可抓出positionalparameter的数量.
以前面的my.
shp1"p2p3"为例:由于p2与p3之间的IFS是在softquote中,因此$#可得到2的值.
但如果p2与p3没有置于quoting中话,那$#就可得到3的值了.
同样的道理在function中也是一样的.
.
.
因此,我们常在shellscript里用如下方法测试script是否有读进参数:代码:[$#=0]假如为0,那就表示script没有参数,否则就是有带参数.
.
.
接下来就是$@与$*:精确来讲,两者只有在softquote中才有差异,否则,都表示"全部参数"($0除外).
举例来说好了:若在commandline上跑my.
shp1"p2p3"p4的话,不管是$@还是$*,都可得到p1p2p3p4就是了.
但是,如果置于softquote中的话:"$@"则可得到"p1""p2p3""p4"这三个不同的词段(word)﹔"$*"则可得到"p1p2p3p4"这一整串单一的词段.
我们可修改一下前面的my.
sh,使之内容如下:代码:#!
/bin/bashmy_fun(){echo"$#"}echo'thenumberofparameterin"$@"is'$(my_fun"$@")echo'thenumberofparameterin"$*"is'$(my_fun"$*")然后再执行.
/my.
shp1"p2p3"p4就知道$@与$*差在哪了.
.
.
^_^10)&&与||差在哪好不容易,进入两位数的章节了.
.
.
一路走来,很辛苦吧也很快乐吧^_^在解答本章题目之前,先让我们了解一个概念:returnvalue﹗我们在shell下跑的每一个command或function,在结束的时候都会传回父行程一个值,称为returnvalue.
在shellcommandline中可用$这个变量得到最"新"的一个returnvalue,也就是刚结束的那个行程传回的值.
ReturnValue(RV)的取值为0-255之间,由程序(或script)的作者自行定议:*若在script里,用exitRV来指定其值,若没指定,在结束时以最后一道命令之RV为值.
*若在function里,则用returnRV来代替exitRV即可.
ReturnValue的作用,是用来判断行程的退出状态(exitstatus),只有两种:*0的话为"真"(true)*非0的话为"假"(false)举个例子来说明好了:假设当前目录内有一份my.
file的文件,而no.
file是不存在的:代码:$touchmy.
file$lsmy.
file$echo$#firstecho0$lsno.
filels:no.
file:Nosuchfileordirectory$echo$#secondecho1$echo$#thirdecho0上例的第一个echo是关于lsmy.
file的RV,可得到0的值,因此为true﹔第二个echo是关于lsno.
file的RV,则得到非0的值,因此为false﹔第三个echo是关于第二个echo$的RV,为0的值,因此也为true.
请记住:每一个command在结束时都会送回returnvalue的﹗不管你跑甚么样的命令.
.
.
然而,有一个命令却是"专门"用来测试某一条件而送出returnvalue以供true或false的判断,它就是test命令了﹗若你用的是bash,请在commandline下打mantest或manbash来了解这个test的用法.
这是你可用作参考的最精确的文件了,要是听别人说的,仅作参考就好.
.
.

下面我只简单作一些辅助说明,其余的一律以man为准:首先,test的表示式我们称为expression,其命令格式有两种:代码:testexpressionor:[expression](请务必注意[]之间的空格键﹗)用哪一种格式没所谓,都是一样的效果.
(我个人比较喜欢后者.
.
.
)其次,bash的test目前支持的测试对像只有三种:*string:字符串,也就是纯文字.
*integer:整数(0或正整数,不含负数或小数点).
*file:文件.
请初学者一定要搞清楚这三者的差异,因为test所用的expression是不一样的.
以A=123这个变量为例:*["$A"=123]:是字符串的测试,以测试$A是否为1、2、3这三个连续的"文字".
*["$A"-eq123]:是整数的测试,以测试$A是否等于"一百二十三".
*[-e"$A"]:是关于文件的测试,以测试123这份"文件"是否存在.
第三,当expression测试为"真"时,test就送回0(true)的returnvalue,否则送出非0(false).
若在expression之前加上一个"!
"(感叹号),则是当expression为"假时"才送出0,否则送出非0.
同时,test也允许多重的覆合测试:*expression1-aexpression2:当两个exrepssion都为true,才送出0,否则送出非0.
*expression1-oexpression2:只需其中一个exrepssion为true,就送出0,只有两者都为false才送出非0.
例如:代码:[-d"$file"-a-x"$file"]是表示当$file是一个目录、且同时具有x权限时,test才会为true.
第四,在commandline中使用test时,请别忘记命令行的"重组"特性,也就是在碰到meta时会先处理meta再重新组建命令行.
(这个特性我在第二及第四章都曾反复强调过)比方说,若test碰到变量或命令替换时,若不能满足expression格式时,将会得到语法错误的结果.
举例来说好了:关于[string1=string2]这个test格式,在=号两边必须要有字符串,其中包括空(null)字符串(可用softquote或hardquote取得).
假如$A目前没有定义,或被定议为空字符串的话,那如下的写法将会失败:代码:$unsetA$[$A=abc][:=:unaryoperatorexpected这是因为命令行碰到$这个meta时,会替换$A的值,然后再重组命令行,那就变成了:[=abc]如此一来=号左边就没有字符串存在了,因此造成test的语法错误﹗但是,下面这个写法则是成立的:代码:$["$A"=abc]$echo$1这是因为在命令行重组后的结果为:[""=abc]由于=左边我们用softquote得到一个空字符串,而让test语法得以通过.
.
.
读者诸君请务必留意这些细节哦,因为稍一不慎,将会导至test的结果变了个样﹗若您对test还不是很有经验的话,那在使用test时不妨先采用如下这一个"法则":*假如在test中碰到变量替换,用softquote是最保险的﹗若你对quoting不熟的话,请重新温习第四章的内容吧.
.
.
^_^okay,关于更多的test用法,老话一句:请看manpage吧﹗^_^虽然洋洋洒洒讲了一大堆,或许你还在嘀咕.
.
.
.
那.
.
.
那个returnvalue有啥用啊﹗问得好﹗告诉你:returnvalue的作用可大了﹗若你想让你的shell变"聪明"的话,就全靠它了:*有了returnvalue,我们可以让shell跟据不同的状态做不同的时情.
.
.
这时候,才让我来揭晓本章的答案吧~~~^_^&&与||都是用来"组建"多个commandline用的:*command1&&command2:其意思是command2只有在RV为0(true)的条件下执行.
*command1||command2:其意思是command2只有在RV为非0(false)的条件下执行.
来,以例子来说好了:代码:$A=123$[-n"$A"]&&echo"yes!
it'sture.
"yes!
it'sture.
$unsetA$[-n"$A"]&&echo"yes!
it'sture.
"$[-n"$A"]||echo"no,it'sNOTture.
"no,it'sNOTture.
(注:[-nstring]是测试string长度大于0则为true.
)上例的第一个&&命令行之所以会执行其右边的echo命令,是因为上一个test送回了0的RV值﹔但第二次就不会执行,因为为test送回非0的结果.
.
.
同理,||右边的echo会被执行,却正是因为左边的test送回非0所引起的.
事实上,我们在同一命令行中,可用多个&&或||来组建呢:代码:$A=123$[-n"$A"]&&echo"yes!
it'sture.
"||echo"no,it'sNOTture.
"yes!
it'sture.
$unsetA$[-n"$A"]&&echo"yes!
it'sture.
"||echo"no,it'sNOTture.
"no,it'sNOTture.
怎样,从这一刻开始,你是否觉得我们的shell是"很聪明"的呢^_^好了,最后,布置一道习题给大家做做看、、、下面的判断是:当$A被赋与值时,再看是否小于100,否则送出toobig!
:代码:$A=123$[-n"$A"A"-lt100]||echo'toobig!
'toobig!
若我将A取消,照理说,应该不会送文字才对啊(因为第一个条件就不成立了).
.
.
代码:$unsetA$[-n"$A"A"-lt100]||echo'toobig!
'toobig!
为何上面的结果也可得到呢又,如何解决之呢(提示:修改方法很多,其中一种方法可利用第七章介绍过的commandgroup.
.
.
)快﹗告我我答案﹗其余免谈.
.
.
.
11)>与来改变送出的数据信道(stdout,stderr),使之输出到指定的档案.
比方说:代码:$cat又如何呢且听下回分解.
.
.
.
11.
3okay,又到讲古时间~~~当你搞懂了0*2>前者是改变stdout的数据输出信道,后者是改变stderr的数据输出信道.
两者都是将原本要送出到monitor的数据转向输出到指定档案去.
由于1是>的默认值,因此,1>与>是相同的,都是改stdout.
用上次的ls例子来说明一下好了:代码:$lsmy.
fileno.
such.
file1>file.
outls:no.
such.
file:Nosuchfileordirectory这样monitor就只剩下stderr而已.
因为stdout给写进file.
out去了.
代码:$lsmy.
fileno.
such.
file2>file.
errmy.
file这样monitor就只剩下stdout,因为stderr写进了file.
err.
代码:$lsmy.
fileno.
such.
file1>file.
out2>file.
err这样monitor就啥也没有,因为stdout与stderr都给转到档案去了.
.
.
呵~~~看来要理解>一点也不难啦﹗是不没骗你吧^_^不过,有些地方还是要注意一下的.
首先,是filelocking的问题.
比方如下这个例子:代码:$lsmy.
fileno.
such.
file1>file.
both2>file.
both从filesystem的角度来说,单一档案在单一时间内,只能被单一的FD作写入.
假如stdout(1)与stderr(2)都同时在写入file.
both的话,则要看它们在写入时否碰到同时竞争的情形了,基本上是"先抢先赢"的原则.

让我们用周星驰式的"慢镜头"来看一下stdout与stderr同时写入file.
out的情形好了:*第1,2,3秒为stdout写入*第3,4,5秒为stderr写入那么,这时候stderr的第3秒所写的数据就丢失掉了﹗要是我们能控制stderr必须等stdout写完再写,或倒过来,stdout等stderr写完再写,那问题就能解决.
但从技术上,较难掌控的,尤其是FD在作"长期性"的写入时.
.
.
那,如何解决呢所谓山不转路转、路不转人转嘛,我们可以换一个思维:将stderr导进stdout或将stdout导进sterr,而不是大家在抢同一份档案,不就行了﹗bingo﹗就是这样啦:*2>&1就是将stderr并进stdout作输出*1>&2或>&2就是将stdout并进stderr作输出于是,前面的错误操作可以改为:代码:$lsmy.
fileno.
such.
file1>file.
both2>&1或$lsmy.
fileno.
such.
file2>file.
both>&2这样,不就皆大欢喜了吗呵~~~^_^不过,光解决了locking的问题还不够,我们还有其它技巧需要了解的.
故事还没结束,别走开﹗广告后,我们再回来.
.
.
﹗11.
4okay,这次不讲I/ORedirction,讲佛吧.
.
.
(有没搞错﹗网中人是否头壳烧坏了.
.
.
)嘻~~~^_^学佛的最高境界,就是"四大皆空".
至于是空哪四大块我也不知,因为我还没到那境界.
.
.

但这个"空"字,却非常值得我们返复把玩的:---色即是空、空即是色﹗好了,施主要是能够领会"空"的禅意,那离修成正果不远矣~~~在Linux档案系统里,有个设备档位于/dev/null.
许多人都问过我那是甚么玩意儿我跟你说好了:那就是"空"啦﹗没错﹗空空如也的空就是null了.
.
.
.
请问施主是否忽然有所顿误了呢然则恭喜了~~~^_^这个null在I/ORedirection中可有用得很呢:*若将FD1跟FD2转到/dev/null去,就可将stdout与stderr弄不见掉.
*若将FD0接到/dev/null来,那就是读进nothing.
比方说,当我们在执行一个程序时,画面会同时送出stdout跟stderr,假如你不想看到stderr(也不想存到档案去),那可以:代码:$lsmy.
fileno.
such.
file2>/dev/nullmy.
file若要相反:只想看到stderr呢还不简单﹗将stdout弄到null就行:代码:$lsmy.
fileno.
such.
file>/dev/nullls:no.
such.
file:Nosuchfileordirectory那接下来,假如单纯只跑程序,不想看到任何输出结果呢哦,这里留了一手上次节目没讲的法子,专门赠予有缘人﹗.
.
.
^_^除了用>/dev/null2>&1之外,你还可以如此:代码:$lsmy.
fileno.
such.
file&>/dev/null(提示:将&>换成>&也行啦~~!
)okay讲完佛,接下来,再让我们看看如下情况:代码:$echo"1">file.
out$catfile.
out1$echo"2">file.
out$catfile.
out2看来,我们在重导stdout或stderr进一份档案时,似乎永远只获得最后一次导入的结果.
那,之前的内容呢呵~~~要解决这个问提很简单啦,将>换成>>就好:代码:$echo"3">>file.
out$catfile.
out23如此一来,被重导的目标档案之内容并不会失去,而新的内容则一直增加在最后面去.

零途云:香港站群云服务器16IP220元/月,云服务器低至39元/月

零途云(Lingtuyun.com)新上了香港站群云服务器 – CN2精品线路,香港多ip站群云服务器16IP/5M带宽,4H4G仅220元/月,还有美国200g高防云服务器低至39元/月起。零途云是一家香港公司,主要产品香港cn2 gia线路、美国Cera线路云主机,美国CERA高防服务器,日本CN2直连服务器;同时提供香港多ip站群云服务器。即日起,购买香港/美国/日本云服务器享受9折优惠,新...

MineServer:洛杉矶CN2 GIA VPS/512MB内存/20GB NVME/800GB流量/200Mbps/KVM,58元/季

mineserver怎么样?mineserver是一家国人商家,主要提供香港CN2 KVM VPS、香港CMI KVM VPS、日本CN2 KVM VPS、洛杉矶cn2 gia端口转发等服务,之前介绍过几次,最近比较活跃。这家新推出了洛杉矶CN2 GIA VPS,512MB内存/20GB NVME/800GB流量/200Mbps/KVM,58元/季,并且进行了带宽升级,同时IP更改为美国IP。点击...

Vultr VPS新增第18个数据中心 瑞典斯德哥尔摩欧洲VPS主机机房

前几天还在和做外贸业务的网友聊着有哪些欧洲机房的云服务器、VPS商家值得选择的。其中介绍他选择的还是我们熟悉的Vultr VPS服务商,拥有比较多达到17个数据中心,这不今天在登录VULTR商家的时候看到消息又新增一个新的机房。这算是第18个数据中心,也是欧洲VPS主机,地区是瑞典斯德哥尔摩。如果我们有需要欧洲机房的朋友现在就可以看到开通的机房中有可以选择瑞典机房。目前欧洲已经有五个机房可以选择,...

子目录为你推荐
涡轮增压和自然吸气哪个好涡轮增压和自然吸气哪个好华为p40和mate30哪个好华为p40手机。跟荣耀30哪个好?手机杀毒软件哪个好手机杀毒软件那个好用无纺布和熔喷布口罩哪个好无纺布除了做尿布湿口罩这些,还有其他什么用处吗?网校哪个好会计网校哪个好dnf魔枪士转职哪个好dnf魔枪士转职哪个适合平民玩红茶和绿茶哪个好红茶和绿茶 那个更好视频软件哪个好什么看视频的软件好电信10000宽带测速电信宽带最多有几兆的网速?首选dns服务器首选DNS服务器和备用DNS服务器有什么区别?
黑龙江域名注册 广州服务器租用 最新代理服务器地址 新网域名管理 virpus 免费ftp空间 万网优惠券 服务器怎么绑定域名 网站cdn加速 789电视剧 丽萨 cxz 申请免费空间 如何登陆阿里云邮箱 服务器防御 数据湾 碳云 空间排行榜 winds 美国vpn代理 更多