• bash4----进阶1 内部变量


    0、操作符之求最小公约数

    #!/bin/bash
    
    ARGS=2
    E_BADARGS=65
    
    #args check
    #---------------------------------------
    if [ "$ARGS" -ne $# ]
        then
        echo "Usage: `basename $0` num1 num2 "    
        exit E_BADARGS
    fi
    #---------------------------------------
    
    gcd()
    {
        divisor=$1
        dividend=$2
        remainder=1
        until [ remainder -eq 0 ]
        do
        let "remainder=$dividend%$divisor"
        dividend=$divisor
        divisor=$remainder
        done
    }
    
    gcd $1 $2
        echo "the gcd of $1 and $2 is $dividend"
    exit 0
    

     

    1、内部变量

      $BASH  echo $BASH  ---->  /bin/bash

      $FUNCTION        ---->  当前函数的名字

      $GROUP        ---->  用户所在的组

      $HOME          ---->  /home/username

      $MACHTYPE      ---->  标识系统的硬件(x86_64-pc-linux-gnu)

    ***   $OLDPWD       ---->  之前的工作目录

      $PWD            ---->  工作目录

      $OSTYPE        ---->  操作系统类型

    ***   $PATH          ---->  可执行文件的搜索路径

     当给出一个命令时, shell会自动生成一张哈希(hash)表, 并且在这张哈希表中按照path变量中所列出的路径来搜索这个可执行命令. 路径会存储在环境变量中, $PATH变量本身就一个以冒号分隔的目录列表. 通常情况下, 系统都是在/etc/profile~/.bashrc中存储$PATH的定义.

      其中PATH=${path}:/opt/bin   会把/opt/bin附加到当前目录中,在脚本中,只会临时添加,当这个脚本退出时$PATH会恢复以前的值

      $PPID            进程的$PPID就是这个进程的父进程的ID

      $PROMPT_COMMAND    这个变量保存了在主提示符$PS1显示之前需要执行的命令

      $PS1            主提示符

      $PS2            第二提示符默认显示为'>'

      $PS3            第三提示符,他在一个select循环中显示

      $PS4            第四提示符,当你使用-x选项来调试脚本时,这个提示符会出现在每一行输出的开头,默认显示为+ 

      $SHLVL             Shell级别, 就是Bash被嵌套的深度. 如果是在命令行中, 那么$SHLVL为1, 如果在脚本中那么$SHLVL为2.

      1.1$IFS 内部域分隔符

        对于for arg in "$var1 var2 var3"

          第一次循环,arg=$var1

          第二次循环,arg=$var2

          。。。。

        这里的var1 和var2之间由IFS进行单词分割,如果不想进行单词分割 需要加上“”

        所以可以直接写出output_args_one_per_line()函数

     #!/bin/bash
     # $IFS 处理空白与处理其他字符不同.
    
     output_args_one_per_line()
     {
     for arg
     do echo "[$arg]"
     done
     }
    
     echo; echo "IFS=" ""
     echo "-------"
    
     IFS=" "
     var=" a b c "
     output_args_one_per_line $var #
    output_args_one_per_line `echo " a b c "`
    
     [a]
     [b]
     [c]
    
    
     echo; echo "IFS=:"
     echo "-----"
     IFS=:
     var=":a::b:c:::" # 与上边一样, 但是用" "替换了":".
     output_args_one_per_line $var
     #
     # []
     # [a]
     # []
     # [b]
     # [c]
     # []
     # []
     # []
    
     # 同样的事情也会发生在awk的"FS"域中.
    
     # 感谢, Stephane Chazelas.
    
     echo
    
     exit 0
    

     

      2、$REPLY          

      当没有参数变量提供给read命令的时候, 这个变量会作为默认变量提供给read命令. 也可以用于select菜单, 但是只提供所选择变量的编号, 而不是变量本身的值。当且仅当没有变量提供给"read"命令时,12 #+ REPLY才保存最后一个"read"命令读入的值.当输入多个值时$REPLY还是保存着上一个read命令的值,因为变量$fruit被传入到了这个新的"read"命令中。

    #!/bin/bash
    echo
    echo -n "what is your favorite vegetable?"
    read        #A
    echo "Your favorete vegetable is $REPLY"  #A
    echo
    echo -n "What is your favorite fruit?"  
    read fruit    #B
    echo "Your favorite fruit is $fruit."  #B
    echo "But..."
    echo "Value of $REPLY is still $REPLY"  #A

      3、$TMOUT

      如果$TMOUT环境变量被设置为非零值time的话, 那么经过time秒后, shell提示符将会超时. 这将会导致登出(logout).

      9-2.定时输入

    知识点:

      1、$!运行在后台的最后一个作业的PID;$$是本脚本的进程ID

      2、kill命令:

      kill [信号量] PID

      我们可以通过kill -l 来查看信号量有哪些。这里的15是SIGTERM信号终止(区别于9,15是可以被忽略,进程可以用一段时间来正常关闭,一个程序的正常关闭一般需要一段时间来保存进度并释放资源。换句话说,它不是强制停止。)

      同理trap commands signals,也可以通过trap -l查找信号量。结果差不多相同(我没有注意比较)

      -信号"可使用信号代码或信号名称。kill后可跟多个进程编号,kill会把指定的信号都传递给这些进程。如果省略"-信号"则默认传送SIGTERM(代码15,终止进程)信号给进程。 只要系统产生特定信号,trap就会触发指令。trap 'echo 123' ABRT ; kill -ABRT $$ 屏幕会出现123 $$代表当前shell进程编号

      trap "" HUP INT QUIT KILL     #则会屏蔽HUP INT QUIT KILL这几个信号。

      3、这个脚本的顺序:先echo "what is your favorite..."

            然后执行函数TimerOn和read

          如果函数TimerOn等待超过TIMELIMIT则执行TimerOn中的kill,陷入Int14Vector函数,赋值answer=TIMEOUT并执行PrintAnswer。这个里面TimerOn函数已经在后台运行完成了,所以不需要kill

          如果函数TimerOn等待不超过TIMELIMIT,read就已经完成,则直接执行PrintAnswer并kill还在后台运行的TimerOn函数用$!

    #!/bin/bash
     # timed-input.sh
    
     # TMOUT=3 在新一些的Bash版本上也能运行的很好.
    
    
     TIMELIMIT=3 # 这个例子中设置的是3秒. 也可以设置为其他的时间值.
    
     PrintAnswer()
     {
     if [ "$answer" = TIMEOUT ]
     then
     echo $answer
     else # 别和上边的例子弄混了.
     echo "Your favorite veggie is $answer"
     kill $! # 不再需要后台运行的TimerOn函数了, kill了吧.
     # $! 变量是上一个在后台运行的作业的PID.
     fi
    
     }
    
    
    
     TimerOn()
     {
     sleep $TIMELIMIT && kill -s 14 $$ &
     # 等待3秒, 然后给脚本发送一个信号.
     }
    
     Int14Vector()
     {
     answer="TIMEOUT"
     PrintAnswer
     exit 14
     }
     trap Int14Vector 14 # 定时中断(14)会暗中给定时间限制.
    
     echo "What is your favorite vegetable "
     TimerOn
     read answer
     PrintAnswer
    
    
     # 无可否认, 这是一个定时输入的复杂实现,
     #+ 然而"read"命令的"-t"选项可以简化这个任务.
     # 参考后边的"t-out.sh".
    
     # 如果你需要一个真正优雅的写法...
     #+ 建议你使用C或C++来重写这个应用,
     #+ 你可以使用合适的函数库, 比如'alarm'和'setitimer'来完成这个任务.
    
     exit 0
    

     

     使用stty写的另外一个定时输入:

      更多关于stty的详细描述,可以查看这个博文

      命令stty: 

      stty [option] [setting]...

      例如:设置一个擦除字符

      stty erase '#'  #将backspace(^?)改成了'#'用来退格。

      这里的erase是option中的特殊字符设置。

      设置分为:control setting.input setting. output setting local setting combination setting characters setting special setting .

        另外stty -a是使用用户可读的方式输出设置

        stty -g是用stty方式输出(具体用法就是其中一个如下代码)

         old_tty_settings=`stty -g`    #保存旧的tty在变量中

       stty -icanon min 0 time ${timeout}0  #[-]icanon    启用erase、kill、werase 和rprnt 等特殊字符

                        #min N        和 -icanon 配合使用,设置每次一完整读入的最小字符数为<N>

                        # time N       和-icanon 配合使用,设置读取超时为N 个十分之一秒(因为是N个十分之一秒,所以后面要加个0,才是对应秒数)

       eval read $varname   # eval [parameter]:参数说明:参数不限数目,彼此之间用分号分开。

                   #eval 执行以下两个步骤:
                   #第一步,执行变量替换,类似与C语言的宏替代;
                   #第二步,执行替换后的命令串。  

                   #eg:WORD="cat test"; echo $WORD;eval $WORD

                   #echo显示cat test 而eval 则把变量替换,然后执行命令。

      另外,$#表示位置参数的个数,所以echo $$#表示$参数个数,而echo $$#表示PID#,所以为了得到最后一个参数可以eval echo $$#

    #!/bin/bash
     # timeout.sh
    
     # 由Stephane Chazelas所编写,
     #+ 本书作者做了一些修改.  
    
     INTERVAL=5 # 超时间隔
     timedout_read() {
     timeout=$1
     varname=$2
     old_tty_settings=`stty -g`
     stty -icanon min 0 time ${timeout}0
     eval read $varname # 或者仅仅读取$varname变量
     stty "$old_tty_settings"
     # 参考"stty"的man页.
     }
    
     echo; echo -n "What's your name? Quick! "
     timedout_read $INTERVAL your_name
    
     # 这种方法可能并不是在每种终端类型上都可以正常使用的.
     # 最大的超时时间依赖于具体的中断类型.
     #+ (通常是25.5秒).
    
     echo
    
     if [ ! -z "$your_name" ] # 如果在超时之前名字被键入...
     then
     echo "Your name is $your_name."
     else
     echo "Timed out."
     fi
    
     echo
    
     # 这个脚本的行为可能与脚本"timed-input.sh"的行为有些不同.
     # 每次按键, 计时器都会重置(译者注: 就是从0开始).
    
     exit 0
    

      

     另外 read -t TIMELIMIT varname 也可以定时输入,具体代码不再写出。

      如何判断用户ID?

    root是$UID=0

    另外可以通过命令`id -nu`或`whoami`来判断

    "$*"和"$@“和$*的区别:

    1、“$*”会将所有的参数看做一个单词

    2、$*和$@将会把参数看成单独的单词

    3、$@和$*中的参数表现取决于$IFS的设置。

    4、$@可以作为工具使用,用来过滤传递给脚本的输入,同时shift命令结合使用。shift一次后,$1就丢弃了,$@保存剩下的。

    5、当$@和$*被双引号引用时候,那么参数会有所不同。(不要用双引号!)

    6、当$IFS为空时,则$*和$@的行为依赖与bash和sh的版本特性。

    $!是运行在后台的一个作业的PID。

    $_这个变量保存之前执行的命令的最后一个参数的值。

    $?命令,函数,或者是脚本本身的退出状态码

    $$脚本自身的进程ID。$$变量在脚本中经常用来构造”唯一的“临时文件名。这么做通常比调用mktemp命令简单一些。EG:TEMPFILE=/tmp/ftp.$$

  • 相关阅读:
    作用域和内存问题
    Javascript事件
    JavaScript学习总结(三)
    Javascript学习总结(二)
    JavaScript学习总结(一)
    vue开发搭建 1、 npm安装+vue脚手架安装 2、cnpm安装
    20181008
    RabbitMQ在.NetCore中的基础应用
    微软CRM 基于 ADFS自定义多重身份验证
    如何在ASP.NET Core中上传超大文件
  • 原文地址:https://www.cnblogs.com/SsoZhNO-1/p/9282066.html
Copyright © 2020-2023  润新知