设为首页 收藏本站
查看: 609|回复: 0

细读shell-2

[复制链接]

尚未签到

发表于 2018-8-24 10:58:10 | 显示全部楼层 |阅读模式
  9 . var=value?export 前后差在哪?
  来了解一下 bash 变量(variable)吧
  所谓的变量,就是利用一个特定的"名称"(name)来存取一段可以变化的"值"(value)。
  *设定(set)*
  在 bash 中,你可以用 "=" 来设定或重新定义变量的内容:
  name=value
  在设定变量的时侯,得遵守如下规则:
  * 等号左右两边不能使用区隔符号(IFS), 也应避免使用 shell 的保留字符(meta charactor)。
  * 变量名称不能使用 $ 符号。
  * 变量名称的第一个字母不能是数字(number)。
  * 变量名称长度不可超过 256 个字母。
  * 变量名称及变量值之大小写是有区别的(case sensitive)。
  如下是一些变量设定时常见的错误:
  A= B :不能有 IFS
  1A=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
  代码:
  ls -la /tmp
  利用 shell 对变量的替换处理能力,我们在设定变量时就更为灵活了:
  A=B
  B=$A
  这样,B 的变量值就可继承 A 变量"当时"的变量值了。
  不过,不要以"数学罗辑"来套用变量的设定,比方说:
  A=B
  B=C
  这样并不会让 A 的变量值变成 C 。再如:
  A=B
  B=$A
  A=C
  同样也不会让 B 的值换成 C 。
  上面是单纯定义了两个不同名称的变量:A 与 B ,它们的值分别是 B 与 C 。
  若变量被重复定义的话,则原有旧值将被新值所取代。(这不正是"可变的量"吗? ^_^)
  当我们在设定变量的时侯,请记着这点:
  * 用一个名称储存一个数值
  此外,我们也可利用命令行的变量替换能力来"扩充"(append)变量值:
  A=B:C:D
  A=$A:E
  这样,第一行我们设定 A 的值为 "B:C:D",然后,第二行再将值扩充为 "A:B:C:E" 。
  上面的扩充范例,我们使用区隔符号( : )来达到扩充目的,
  要是没有区隔符号的话,如下是有问题的:
  A=BCD
  A=$AE
  因为第二次是将 A 的值继承 $AE 的提换结果,而非 $A 再加 E ﹗
  要解决此问题,我们可用更严谨的替换处理:
  A=BCD
  A=${A}E
  上例中,我们使用 {} 将变量名称的范围给明确定义出来,
  如此一来,我们就可以将 A 的变量值从 BCD 给扩充为 BCDE 。
  
  10.* export *
  严格来说,我们在当前 shell 中所定义的变量,均属于"本地变量"(local variable),
  只有经过 export 命令的"输出"处理,才能成为环境变量(environment variable):
  代码:
  $ A=B
  $ export A
  或:
  代码:
  $ export A=B
  经过 export 输出处理之后,变量 A 就能成为一个环境变量供其后的命令使用。
  在使用 export 的时侯,请别忘记 shell 在命令行对变量的"替换"(substitution)处理,
  比方说:
  $ A=B
  $ B=C
  $ export $A
  上面的命令并未将 A 输出为环境变量,而是将 B 作输出,
  这是因为在这个命令行中,$A 会首先被提换出 B 然后再"塞回"作 export 的参数。
  *取消变量*
  要取消一个变量,在 bash 中可使用 unset 命令来处理:
  与 export 一样,unset 命令行也同样会作变量替换(这其实就是 shell 的功能之一),
  因此:
  $ A=B
  $ B=C
  $ unset $A
  事实上所取消的变量是 B 而不是 A 。
  此外,变量一旦经过 unset 取消之后,其结果是将整个变量拿掉,而不仅是取消其变量值。
  如下两行其实是很不一样的:
  代码:
  $ A=
  $ unset A
  第一行只是将变量 A 设定为"空值"(null value),但第二行则让变量 A 不在存在。
  虽然用眼睛来看,这两种变量状态在如下命令结果中都是一样的:
  代码:
  $ A=
  $ echo $A
  $ unset A
  $ echo $A
  请学员务必能识别 null value 与 unset 的本质区别, 这在一些进阶的变量处理上是很严格的
  比方说:
  $ str=      # 设为 null
  $ var=${str=expr}   # 定义 var
  $ echo $var
  $ echo $str
  $ unset str   # 取消
  $ var=${str=expr}   # 定义 var
  $ echo $var
  expr
  $ echo $str
  expr
  应该不难发现为何同样的 var=${str=expr} 在 null 与 unset 之下的不同吧?
  11. exec 跟 source 差在哪?
  cd /etc/aa/bb/cc可以执行
  但是把这条命令写入shell 时shell 不执行!
  这是什幺原因呀!
  首先, 我们所执行的任何程序,都是由父行程(parent process)所产生出来的一个子行程(child process),  子行程在结束后,将返回到父行程去。此一现像在 Linux 系统中被称为 fork 。
  * 所谓环境变量其实就是那些会传给子行程的变量。
  * 环境变量只能从父行程到子行程单向继承。换句话说:在子行程中的环境如何变更,均不会影响父行程的环境。
  接下来,再让我们了解一下命令脚本(shell script)的概念。
  所谓的 shell script  讲起来很简单,就是将你平时在 shell prompt  后所输入的多行 command line 依序写入一个文件去而已。
  其中再加上一些条件判断、互动界面、参数运用、函数调用、等等技巧,得以让 script 更加"聪明"的执行.
  再结合以上两个概念(process + script),那应该就不难理解如下这句话的意思了:
  * 正常来说,当我们执行一个 shell script 时,其实是先产生一个 sub-shell 的子行
  后 sub-shell 再去产生命令行的子行程。
  引用
  cd /etc/aa/bb/cc可以执行
  但是把这条命令写入shell 时shell 不执行!
  这是什幺原因呀!
  引用:
  因为,一般我们跑的 shell script 是用 subshell 去执行的。
  从 process 的观念来看,是 parent process 产生一个 child process 去执行,
  当 child 结束后,会返回 parent ,但 parent 的环境是不会因 child 的改变而改变的。

  所谓的环境元数很多,凡举 effective>  其中的 workding dir ($PWD) 正是楼主的疑问所在:
  当用 subshell 来跑 script 的话,sub shell 的 $PWD 会因为 cd 而变更,
  但当返回 primary shell 时,$PWD 是不会变更的。
  
  那好,接下来,再让我们了解一下 source 命令好了。
  * 所谓 source 就是让 script 在当前 shell 内执行、而不是产生一个 sub-shell 来执
  由于所有执行结果均于当前 shell 内完成,若 script 的环境有所改变,当然也会改变
  境了﹗
  因此,只要我们要将原本单独输入的 script 命令行变成 source 命令的参数,就可轻
  前例提到的问题了。
  比方说,原本我们是如此执行 script 的:
  ./my.script
  现在改成这样即可:
  source ./my.script
  或:
  . ./my.script
  ---- 那 exec 又与 source/fork 有何不同呢?
  要了解 exec 或许较为复杂,尤其扯上 File Descriptor 的话...
  * exec 也是让 script 在同一个行程上执行,但是原有行程则被结束了。
  也就是简而言之:原有行程会否终止,就是 exec 与 source/fork 的最大差异了。
  下面让我们写两个简单的 script ,分别命令为 1.sh 及 2.sh :
  1.sh
  代码:
  #!/bin/bash
  A=B
  echo "PID for 1.sh before exec/source/fork:$$"
  export A
  echo "1.sh: \$A is $A"
  case $1 in
  exec)
  echo "using exec..."
  exec ./2.sh ;;
  source)
  echo "using source..."
  . ./2.sh ;;
  *)
  echo "using fork by default..."
  ./2.sh ;;
  esac
  echo "PID for 1.sh after exec/source/fork:$$"
  echo "1.sh: \$A is $A"
  2.sh
  #!/bin/bash
  echo "PID for 2.sh: $$"
  echo "2.sh get \$A=$A from 1.sh"
  A=C
  export A
  echo "2.sh: \$A is $A"
  然后,分别跑如下参数来观察结果:
  代码:
  $ ./1.sh fork
  $ ./1.sh source
  $ ./1.sh exec
  
  12.( ) 与 { } 差在哪?
  许多时候,我们在 shell 操作上,需要在一定条件下一次执行多个命令, 也就是说,要么不执行,要么就全执行,而不是每次依序的判断是否要执行下一个命令。
  们就可引入"命令群组"(command group)的概念:将多个命令集中处理。
  虽然两者都可将多个命令作群组化处理,但若从技术细节上,却是很不一样的:
  ( ) 将 command group 置于 sub-shell 去执行,也称 nested sub-shell。
  { } 则是在同一个 shell 内完成,也称为 non-named command group。
  要是在 command group 中扯上变量及其它环境的修改,我们可以根据不同的需求来使用 ( ) 或 { } 。
  13. function
  所谓的 function ,就是用一个名字去命名一个 command group ,然后再调用这个名字去
  执行 command group 。
  从 non-named command group 来推断,大概你也可以猜到我要说的是 { } 了吧?
  在 bash 中,function 的定义方式有两种:
  方法一
  function function_name {
  command1
  command2
  command3
  ....
  }
  方式二:
  fuction_name () {
  command1
  command2
  command3
  ....
  }
  若碰到所定意的名称与现有的命令或别名(Alias)冲突的话,方式二
  或许会失败。
  function 在某一程度来说,也可称为"函式",但请不要与传统编程所使用的函式(library)搞混了,毕竟两者差异很大。
  惟一相同的是,我们都可以随时用"已定义的名称"来调用它们...
  若我们在 shell 操作中,需要不断的重复质行某些命令,我们首先想到的,或许是将命令写成命令稿(shell script)。
  不过,我们也可以写成 function ,然后在 command line 中打上 function_name 就可当一舨的 script 来使用了。
  只是若你在 shell 中定义的 function ,除了可用 unset function_name 取消外,一旦退出shell ,function 也跟着取消。
  然而,在 script 中使用 function 却有许多好处,除了可以提高整体 script 的执行效能外(因为已被加载),
  简单而言,若你会将多个命令写成 script 以供调用的话,那,你可以将 function 看成script 中的 script ... ^_^


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-555897-1-1.html 上篇帖子: nginx shell 安装 下篇帖子: shell批量
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表