zoukankan      html  css  js  c++  java
  • subShell与代码块

    subShell 是一群被括在圆括号里的命令,这些命令会在另外的进程里执行。当你需要让一组命令在不同的目录下执行时,这种方法可以让你不修改主脚本的目录。

    例; 将某个目录树通过管道复制到另外一个地方。

    tar -cf - . | (cd /newdir; tar -xpf - )

    代码块概念上与subShell相同,但是它不会建立新的进程。代码块里的命令用花括号{}括起来,且对主脚本的状态会产生影响。

     子shell: 每个shell脚本都有效地运行在父shell的一个子进程中. 这个父shell指的是在一个控制终端或在一个xterm窗口中给出命令提示符的那个进程.

    shell脚本也能启动它自已的子进程. 这些子shell能够使脚本并行的, 有效的, 同时运行多个子任务.

    圆括号中的命令列表( command1; command2; command3; ... )圆括号中命令列表的命令将会运行在一个子shell中.

    子shell中的变量对于子shell之外的代码块来说, 是不可见的. 当然, 父进程也不能访问这些变量, 父进程指的是产生这个子shell的shell. 事实上, 这些变量都是局部变量.

    子shell中的目录更改不会影响到父shell.

    子shell中的目录更改不会影响到父shell.父shell不受任何影响, 并且父shell的环境也没有被更改.

    子shell的另一个应用, 是可以用来检测一个变量是否被定义.

    [[ ${variable-x} != x || ${variable-y} != y ]]  或 [[ ${variable-x} != x$variable ]]  或 [[ ${variable+x} = x ]]  或  [[ ${variable-x} != x ]]

    使用"|"管道操作符, 将I/O流重定向到一个子shell中, 比如ls -al | (command).

    在大括号中的命令不会启动子shell.{ command1; command2; command3; . . . commandN; }

    Here Document:  一个here document就是一段带有特殊目的的代码段. 它使用I/O重定向的形式将一个命令序列传递到一个交互程序或者命令中, 比如ftp, cat, 或者ex文本编辑器.

      COMMAND <<InputComesFromHERE
              ...
      InputComesFromHERE

    limit string用来界定命令序列的范围(译者注: 两个相同的limit string之间就是命令序列). 特殊符号<<用来标识limit string. 这个符号的作用就是将文件的输出重定向到程序或命令的stdin中.与interactive-program < command-file很相似, 其中command-file包含:
    而here document看上去是下面这个样子:
      #!/bin/bash
      interactive-program <<LimitString
       command #1
       command #2
      ...
       LimitString
    选择一个名字非常诡异limit string能够有效的避免命令列表与limit string重名的问题.

    -选项用来标记here document的limit string (<<-LimitString), 可以抑制输出时前边的tab(不是空格). 这么做可以增加一个脚本的可读性.

    结尾的limit string, 就是here document最后一行的limit string, 必须从第一个字符开始. 它的前面不能够有任何前置的空白. 而在这个limit string后边的空白也会引起异常.空白将会阻止limit string的识别.

    列表结构: "与列表"和"或列表"结构能够提供一种手段, 这种手段能够用来处理一串连续的命令.

    与列表: command-1 && command-2 && command-3 && ... command-n,如果每个命令执行后都返回true(0)的话, 那么命令将会依次执行下去. 如果其中的某个命令返
    回false(非零值)的话, 那么这个命令链就会被打断, 也就是结束执行, (那么第一个返回false的命令, 就是最后一个执行的命令, 其后的命令都不会执行).

    或列表:command-1 || command-2 || command-3 || ... command-n如果每个命令都返回false, 那么命令链就会执行下去. 一旦有一个命令返回true, 命令链就会被打断, 也就是结束执行, (第一个返回true的命令将会是最后一个执行的命令). 显然, 这和"与列表"完全相反.

    与列表和或列表的退出状态码由最后一个命令的退出状态所决定。

    false && true || echo false # false
    # 与下面的结果相同
    ( false && true ) || echo false # false
     # But *not*
     false && ( true || echo false ) # (没有输出)
    #  注意, 以从左到右的顺序进行分组与求值,  这是因为逻辑操作"&&""||"具有相同的优先级.  最好避免这么复杂的情况, 除非你非常了解你到底在做什么.

     进程替换

    进程替换与命令替换很相似. 命令替换把一个命令的结果赋值给一个变量, 比如dir_contents=`ls -al`或xref=$( grep word datafile). 进程替换把一个进程的输出提供给另一个进程(换句话说, 它把一个命令的结果发给了另一个命令).

     用圆括号扩起来的命令>(command) , <(command)启动进程替换. 它使用/dev/fd/<n>文件将圆括号中的进程处理结果发送给另一个进程.在"<"或">"与圆括号之间是没有空格的. 如果加了空格, 会产生错误

    进程替换可以比较两个不同命令的输出, 甚至能够比较同一个命令不同选项情况下的输出.

    comm <(ls -l) <(ls -al)
    diff <(ls $first_directory) <(ls $second_directory)
    cat <(ls -l)  # 等价于ls -l | cat
    sort -k 9 <(ls -l /bin) <(ls -l /usr/bin) <(ls -l /usr/X11R6/bin)  # 列出系统3个主要'bin'目录中的所有文件, 并且按文件名进行排序.   注意是3个(查一下, 上面就3个圆括号)明显不同的命令输出传递给'sort'
    diff <(command1) <(command2) # 给出两个命令输出的不同之处.
    
    while read des what mask iface; do
     echo $des $what $mask $iface
    done < <(route -n)
    一个更容易理解的等价代码是:
    route -n |
    while read des what mask iface; do # 管道的输出被赋值给了变量. 
    echo $des $what $mask $iface
    done #  这将产生出与上边相同的输出. 然而, Ulrich Gayer指出. . .这个简单的等价版本在while循环中使用了一个子shell,  因此当管道结束后, 变量就消失了.

    Shell中脚本变量和函数变量的作用域   http://blog.csdn.net/ltx19860420/article/details/5570902

    (1)Shell脚本中定义的变量是global的,其作用域从被定义的地方开始,到shell结束或被显示删除的地方为止。解析:脚本变量v1的作用域从被定义的地方开始,到shell结束。调用函数ltx_func的地方在变量v1的作用域内,所以能够访问并修改变量v1。

    (2)Shell函数定义的变量默认是global的,其作用域从“函数被调用时执行变量定义的地方”开始,到shell结束或被显示删除处为止。函数定义的变量可以被显示定义成local的,其作用域局限于函数内。但请注意,函数的参数是local的。

    解析:函数变量v2默认是global的,其作用域从“函数被调用时执行变量定义的地方”开始,到shell结束为止。注意,不是从定义函数的地方开始,而是从调用函数的地方开始。打印命令在变量v2的作用域内,所以能够访问变量v2。

     解析:函数变量v2显示定义为local的,其作用域局限于函数内。打印命令在函数外,不在变量v2的作用域内,所以能够不能访问变量v2。函数参数是local的,通过位置变量来访问。打印命令输出函数的第一个参数。

    (3)如果同名,Shell函数定义的local变量会屏蔽脚本定义的global变量。

     在函数被调用之前, 所有在函数中声明的变量, 在函数体外都是不可见的,当然也包括那些被明确声明为local的变量.

    退出状态码
    函数返回一个值, 被称为退出状态码. 退出状态码可以由return命令明确指定, 也可以由函数中最后一条命令的退出状态码来指定(如果成功则返回0, 否则返回非0值). 可以在脚本中使用$?来引用退出状态码. 因为有了这种机制, 所以脚本函数也可以象C函数一样有"返回值".
    return终止一个函数. return命令 [1]可选的允许带一个整型参数, 这个整数将作为函数的"退出状态码"返回给调用这个函数的脚本, 并且这个整数也被赋值给变量$?.函数所能返回最大的正整数是255.  为了让函数可以返回字符串或是数组, 可以使用一个在函数外可见的专用全局变量.

    重定向函数的stdin函数本质上其实就是一个代码块, 这就意味着它的stdin可以被重定向.

    2:shell什么情况下会产生子进程
     
    以下几个创建子进程的情况。(以下英文摘自info bash)
    1:&,提交后台作业
    If a command is terminated by the control operator `&', the shell executes the command asynchronously in a subshell.
    2:管道
    Each command in a pipeline is executed in its own subshell
    3:括号命令列表
    ()操作符
         Placing a list of commands between parentheses causes a subshell
         environment to be created
    4:执行外部脚本、程序:
    When Bash finds such a file while searching the `$PATH' for a command, it spawns a subshell to execute it.  In other words, executing
                         filename ARGUMENTS
            is equivalent to executing
                       bash filename ARGUMENTS
     
    说明:大致上子进程的创建包括以上四种情况了。需要说明的是只要是符合上边四种情况之一,便会创建(fork)子进程,不因是否是函数,命令,或程序,也不会因为是内置函数(buitin)或是外部程序。
  • 相关阅读:
    集训第六周 O题
    集训第六周 M题
    集训第六周 矩阵快速幂 K题
    集训第六周 数学概念与方法 计数 排列 L题
    集训第六周 数学概念与方法 J题 数论,质因数分解
    集训第六周 数学概念与方法 数论 线性方程 I题
    集训第六周 数学概念与方法 概率 N题
    HUAS Summer Contest#4 D题 DP
    集训第六周 数学概念与方法 数论 筛素数 H题
    C语言之六大排序算法
  • 原文地址:https://www.cnblogs.com/fly-xiang-zhao/p/3675642.html
Copyright © 2011-2022 走看看