关闭

Linux shell编程的一些注意事项

1548人阅读 评论(0) 收藏 举报

matters need to attention in linux shell programming

(使用的shell环境是Fedora Core 5下的/bin/bash)

工作机理

在新的环境中编程,首先要了解它的工作机理。
shell是在init-login-passwdcheck-loadprofile之后运行的。
系统初始化完成后,进入Login shell,等待用户登录。合法通过后将根据/etc/passwd文件登记的关于用户的一些基本信息启动用户shell,即这里的bash,然后顺序读 入/etc/profile 和~/.bash_profile配置用户shell的环境。至此,login shell的工作完成,进入用户shell的界面。

bash启动后会自动检查~/.bash_login和~/.bashrc,进一步配置用户自定义的shell环境,这里,根据文件内容
# .bashrc                                           
                                                               
# Source global definitions
if [ -f /etc/bashrc ]; then       
        . /etc/bashrc                            
fi
,引用的是公用的/etc/bashrc,当然也可以在里面加入自己的脚本语句。注销时将检查~/.bash_logout脚本。

在bash中,常用到的环境变量有:
BASH_ENV
If  this  parameter  is  set when bash is executing a shell script, its value is inter-preted as a filename containing commands to initialize the shell, as in ~/.bashrc.  The value of BASH_ENV is subjected to parameter expansion, command substitution, and arith-metic expansion before being interpreted as a file name.  PATH is not  used  to  search for the resultant file name.bash(环境配置文件,通常为~/.bashrc)
LC_ALL This variable overrides the value of LANG and  any  other  LC_  variable  specifying  a locale category.
LANG Used to determine the locale category for any category not specifically selected with a variable starting with LC_.
LC_COLLATE This  variable determines the collation order used when sorting the results of pathname expansion, and determines the behavior of range expressions, equivalence  classes,  and collating sequences within pathname expansion and pattern matching.用于文件名展开,表达式匹配。
LC_CTYPE This variable determines the interpretation of characters and the behavior of character classes within pathname expansion and pattern matching.用于字符翻译(即对你按键的解释)
LC_MESSAGES This variable determines the locale used to translate double-quoted strings preceded by a $.
LC_NUMERIC This variable determines the locale category used for number formatting.
LC_CTYPE,PATH,BASH_VERSION,MACHTYPE,SECONDS,REPLY,GLOBIGNORE,IFS,PS1,PS2。关于数字格式的设定
MACHTYPE
Automatically  set  to  a  string that fully describes the system type on which bash is executing, in the standard gnu cpu-company-system format.  The default is system-depen-dent.(平台描述)
PATH
命令搜索路径
PS1
命令提示符
FUNCNAME An array variable containing the names of all shell functions currently in  the  execu-tion call stack.  The element with index 0 is the name of any currently-executing shell function.  The bottom-most element is "main".  This variable exists only when  a  shell function is executing.  Assignments to FUNCNAME have no effect and return an error sta-tus.  If FUNCNAME is unset, it loses its special properties, even if it is subsequently reset.(命令栈,unset/set后将失效)

RANDOM
Each time this parameter is referenced, a random integer between 0 and 32767 is  gener-ated.   The  sequence of random numbers may be initialized by assigning a value to RAN-DOM.  If RANDOM is unset, it loses its special properties, even if it  is  subsequently reset.(随机数生成器,unset/set后将失效)
IFS
The Internal Field Separator that is used for word splitting  after  expansion  and  to split  lines  into  words  with  the  read  builtin  command.   The  default  value  is ‘‘<space><tab><newline>’’.字段分割符

bash对命令行的解析(process): 处理历史命令替换(it depends)--历史命令的分解--更新历史命令(it depends)--处理引用quote--别名替换和函数定义(it depends)--设置重定向、后台任务和管道--执行变量替换evaluate--执行命令替换--处理文件名替换globbing

bash对解析后的命令的类型要作出判断,以便从文件系统中找到并载入内存。判断的顺序为: bash初始化时定义的别名--bash的关键字(if else)--bash的函数(random)--bash内置命令(hostname)--可定位的可执行程序--未知命令。

shell编程时,最头疼的是shell对命令行的字符会进行一些expansion后才会将这些字符参数传递给实际的命令/进程,如去引用处理 quote rule和文件名展开globbing rule,当参数中有正则表达式或者命令对参数有一些特殊替换规则,匹配模式时,脚本写出来就近乎天书了。

Quoting

引用的形式有两种,单 引号和双引号方式,另一种称法是一种叫hard-quote,另一种叫做soft-quote。单引号屏蔽了所有不可见转化,除了/< newlline>  backslash后面跟换行,这种情况下,/不会被传递到进程如echo中去,而是会过滤到,并取消<newlline>的“命令行输入完 毕”的含义,指示shell继续等待用户在下一行的输入。其它字符(知道下一个单引号出现),包括双引号double quote,反斜杠blackslash,括号brace,货币符号dollar等等都会被原样传递到进程,不做任何expansion,所谓hard- quote。双引号正如我们常见的,作为字符串的界定符号deliminator,保护大多数字符免受展开,为了保证双引号本身和更hard的单引号能被 传递,所以保留了/' 和 /" 中 backslash的转义含义。求值符号$将不再受引号屏蔽,根据$是求值evaluate the variable替换还是调用invoke another command替换还是运算替换((...))形式等等,展开后再传递。

一个例子是find  <path>   <expression>   -exec <command>  "{}" /;根据find的格式要求,-exec将用路径查找结果来替换后面出现的所有{} : {}前后必须有空白,以便{}能够被正确的识别为字段word。exec是Linux 的系统调用,这里的exec后面实际上是另一个命令,而且它们在传入到find之前不能被shell 篡改,所以{} 和 ;  都应该保护起来,方式有多种,如:
-exec more  /{/} /;
-exec more /{ /} /;
-exec more "{}" ";" 等等

Expansion

比引用规则还麻烦的地方!

引自bash的自述man上是这么坦白的:Expansion is performed on the command line after it has been  split  into  words.   There  are seven  kinds  of expansion performed: brace expansion, tilde expansion, parameter and variable expansion, command substitution, arithmetic expansion, word splitting, and pathname expansion.光展开类型就有7种!

brace expansion

类似文件名展开。这里的花括号类似正则表达式里的方括号的使用,表示任选一个,候选项用逗号隔开;或者用 .. 两个句号连接 两端的单个字符或单个整数,表示范围内的集合。可以嵌套使用。如a{b,c,d}e  --->   abe, ace, ade 3个串的集合  ;  {a..z}  --->   a,b,c,d,........,z字母表的集合  ; {0-9}   --->  0, 1, 2,,,,,,9  数字的集合 。另外说明的是:
Brace  expansion is performed before any other expansions, and any characters special to other expansions are preserved in the result.  It is strictly textual.  Bash does not apply any syntactic interpretation to the context of the expansion or the text between the braces.

 
A correctly-formed brace expansion must contain unquoted opening and closing braces, and at  least one unquoted comma or a valid sequence expression. Any incorrectly formed brace expansion is left unchanged.
A { or , may be quoted with a backslash to prevent its being considered part of a brace expression. To avoid conflicts with parameter expansion, the string ${ is not considered eligible for brace expansion.

This construct is typically used as shorthand when the common prefix of the strings to be generated is longer than in the above example:

 mkdir /usr/local/src/bash/{old,new,dist,bugs}
 or
 chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}}

 Brace expansion introduces a slight incompatibility with historical versions of sh. sh does
 not treat opening or closing braces specially when they appear as part of a word, and preserves them in the output. Bash removes braces from words as a consequence of brace expansion. For example, a word entered to sh as file{1,2} appears identically in the output. The
 same word is output as file1 file2 after expansion by bash. If strict compatibility with sh is  desired, start bash with the +B option or disable brace expansion with the +B option to the
 set command (see SHELL BUILTIN COMMANDS below).

tilde expansion 

波浪线替换就是替换成用户主目录变量值,或者更改当前目录变量值,算不上expansion,简单的subistitution而已。
If a word begins with an unquoted tilde character (‘~’), all of the characters  preceding  the
 first  unquoted  slash  (or  all  characters,  if there is no unquoted slash) are considered a
 tilde-prefix.  If none of the characters in the tilde-prefix are quoted, the characters in the
 tilde-prefix  following the tilde are treated as a possible login name.  If this login name is
 the null string, the tilde is replaced with the value of the shell parameter HOME.  If HOME is
 unset,  the home directory of the user executing the shell is substituted instead.  Otherwise,
 the tilde-prefix is replaced with the home directory associated with the specified login name.
 
If  the tilde-prefix is a ‘~+’, the value of the shell variable PWD replaces the tilde-prefix.
 If the tilde-prefix is a ‘~-’, the value of the shell variable OLDPWD, if it is set,  is  sub-
 stituted.   If  the  characters following the tilde in the tilde-prefix consist of a number N,
 optionally prefixed by a ‘+’ or a ‘-’, the tilde-prefix is  replaced  with  the  corresponding
 element  from  the  directory stack, as it would be displayed by the dirs builtin invoked with
 the tilde-prefix as an argument.  If the characters following the tilde  in  the  tilde-prefix
 consist of a number without a leading ‘+’ or ‘-’, ‘+’ is assumed.
 
If the login name is invalid, or the tilde expansion fails, the word is unchanged.
 
Each  variable  assignment is checked for unquoted tilde-prefixes immediately following a : or
 the first =.  In these cases, tilde expansion is also performed.  Consequently,  one  may  use
 file names with tildes in assignments to PATH, MAILPATH, and CDPATH, and the shell assigns the
 expanded value.

parameter and variable expansion

变量替换,或者称作引用变量值
The ‘$’ character introduces parameter expansion, command substitution, or  arithmetic  expansion.   The  parameter  name  or  symbol  to  be expanded may be enclosed in braces, which are optional but serve to protect the variable to be expanded from characters immediately  following it which could be interpreted as part of the name.

       When braces are used, the matching ending brace is the first ‘}’ not escaped by a backslash or within a quoted string, and not within an embedded arithmetic expansion, command substitution, or parameter expansion.
这种类似scheme中的求值运算符天生不容易混乱,当使用花括号把待求值的部分保护起来后,完全不存在其它屏蔽-渗透交叉的麻烦: 除非遇到豁免的},不然字符全部渗透且限定在$层参与求值,所以$是不可以嵌套的,内层$求值将不被认可。

command substitution
arithmetic expansion
word splitting
pathname expansion


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:559516次
    • 积分:7046
    • 等级:
    • 排名:第3332名
    • 原创:155篇
    • 转载:82篇
    • 译文:2篇
    • 评论:128条
    文章分类
    最新评论