shell中的循环语法

Posted 尹正杰

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了shell中的循环语法相关的知识,希望对你有一定的参考价值。

                 SHELL脚本编程配置环境

                                                     作者:尹正杰

版权声明:原创作品,谢绝转载!否则将追究法律责任。

 
 
 
一.bash如何展开命令行
1>.bash的优先级
  把命令行分成单个命令词
  展开别名
  展开大括号的声明({})
  展开波浪符声明(
~
  命令替换$() 和 ``)
  再次把命令行分成命令词
  展开文件通配(
*、?、[abc]等等)
  准备I
/0重导向(<、>
  运行命令
2>.反斜线(\\)会使随后的字符按原意解释
[root@node101.yinzhengjie.org.cn ~]# echo Your cost:\\$15.00
Your cost:$15.00
[root@node101.yinzhengjie.org.cn ~]# 
3>.加引号来防止扩展
    单引号(\'\')防止所有扩展

    双引号("")也可防止扩展,但是以下情况例外:
    $(美元符号):
      变量扩展     ` `(反引号):
      命令替换     \\(反斜线):
      禁止单个字符扩展     !(
叹号):
      历史命令替换

 

二.bash的配置文件
按生效范围划分,存在两类:
  全局配置:
    /etc/profile
    /etc/profile.d/*.sh
    /etc/bashrc
  个人配置:
    ~/.bash_profile
    ~/.bashrc
 
三.shell登录两种方式
交互式登录:
  (1)直接通过终端输入账号密码登录
  (2)使用"su -l UserName"切换的用户
  执行顺序:/etc/profile --> /etc/profile.d/*.sh --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc

非交互式登录:
  (1)使用"su UserName"切换的用户
  (2)图形界面下打开的终端
  (3)执行脚本
  (4)任何其它的bash实例
  执行顺序: /etc/profile.d/*.sh --> /etc/bashrc -->~/.bashrc
 
四.Profile类和Bashrc类
按功能划分,存在两类:
  即profile类和bashrc类

profile类:为交互式登录的shell提供配置
  全局:
    /etc/profile, /etc/profile.d/*.sh
  个人:
    ~/.bash_profile
  作用:
    (1)用于定义环境变量
    (2)运行命令或脚本

bashrc类:为非交互式和交互式登录的shell提供配置
  全局:
    /etc/bashrc
  个人:
    ~/.bashrc
  作用:
    (1)定义命令别名和函数
    (2)定义本地变量

  修改profile和bashrc文件后需生效
    两种方法:
      (1)重新启动shell进程
      (2)使用"."或"source"
    例:
      [root@node101.yinzhengjie.org.cn ~]# . ~/.bashrc 
      [root@node101.yinzhengjie.org.cn ~]# 
      [root@node101.yinzhengjie.org.cn ~]# source ~/.bashrc
 
五.Bash退出任务
  保存在~/.bash_logout文件中(用户)

  在退出登录shell时运行

  用于"创建自动备份"或者"清除临时文件"。
 
六.set 命令
1>."$-"变量
h:
  hashall,打开这个选项后,Shell 会将命令所在的路径hash下来,避免每次都要查询。通过set +h将h选项关闭 i:
  interactive
-comments,包含这个选项说明当前的 shell 是一个交互式的 shell。所谓的交互式shell,在脚本中,i选项是关闭的。 m:
  monitor,打开监控模式,就可以通过Job control来控制进程的停止、继续,后台或者前台执行等。 B:
  braceexpand,大括号扩展 H:
  history,H选项打开,可以展开历史列表中的命令,可以通过
!感叹号来完成,例如“!!”返回上最近的一个历史命令,“!n”返回第 n 个历史命令
[root@node101.yinzhengjie.org.cn ~]# echo $-
himBH
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# hash 
hits    command
   1    /usr/bin/ls
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# set +h
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# echo $-
imBH
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# hash 
-bash: hash: hashing disabled
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# set -h
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# echo $-
himBH
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# hash 
hits    command
   1    /usr/bin/ls
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# 
"h"使用案例
[root@node101.yinzhengjie.org.cn ~]# echo $-
himBH
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# echo {a..z}        #支持大括号扩展功能
a b c d e f g h i j k l m n o p q r s t u v w x y z
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# set +B           #禁用大括号功能
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# echo $-          
himH
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# echo {a..z}        #发现禁用大括号功能后,只能原样输出啦~
{a..z}
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# 
"B"使用案例
[root@node101.yinzhengjie.org.cn ~]# history | tail 
 1233  echo {a..z}
 1234  set +B
 1235  echo $-
 1236  echo {a..z}
 1237  history 
 1238  echo $-
 1239  set -B
 1240  echo $-
 1241  history | tail -5
 1242  history | tail 
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# !-7          #可以正常使用histrory相关命令
echo {a..z}
a b c d e f g h i j k l m n o p q r s t u v w x y z
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# echo $-
himBH
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# set +H        #禁用history
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# echo $-
himB
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# history | tail 
 1240  echo $-
 1241  history | tail -5
 1242  history | tail 
 1243  echo {a..z}
 1244  echo $-
 1245  set -H
 1246  echo $-
 1247  set +H
 1248  echo $-
 1249  history | tail 
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# !-2          #发现history相关语法命令不可用啦~
-bash: !-2: command not found
[root@node101.yinzhengjie.org.cn ~]# 
"H"使用案例
[root@node101.yinzhengjie.org.cn ~]# vim shell/test.sh 
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# cat shell/test.sh 
#!/bin/bash
#
#********************************************************************
#Author: yinzhengjie
#QQ: 1053419035
#Date: 2019-11-21
#FileName: test.sh
#URL: http://www.cnblogs.com/yinzhengjie
#Description: The test script
#Copyright notice: original works, no reprint! Otherwise, legal liability will be investigated.
#********************************************************************

echo $-
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# bash shell/test.sh   #我们发现脚本中是没有"-i,-m和-h"选项的
hB
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# echo $-      #查看当前shell支持的功能
himBH
[root@node101.yinzhengjie.org.cn ~]# 
查看脚本中的变量默认的"$-"的值
[root@node101.yinzhengjie.org.cn ~]# cat -n /etc/profile        #注意观察第67行就用到咱们这里说的"$-"变量哟~
     1    # /etc/profile
     2    
     3    # System wide environment and startup programs, for login setup
     4    # Functions and aliases go in /etc/bashrc
     5    
     6    # It\'s NOT a good idea to change this file unless you know what you
     7    # are doing. It\'s much better to create a custom.sh shell script in
     8    # /etc/profile.d/ to make custom changes to your environment, as this
     9    # will prevent the need for merging in future updates.
    10    
    11    pathmunge () {
    12        case ":${PATH}:" in
    13            *:"$1":*)
    14                ;;
    15            *)
    16                if [ "$2" = "after" ] ; then
    17                    PATH=$PATH:$1
    18                else
    19                    PATH=$1:$PATH
    20                fi
    21        esac
    22    }
    23    
    24    
    25    if [ -x /usr/bin/id ]; then
    26        if [ -z "$EUID" ]; then
    27            # ksh workaround
    28            EUID=`/usr/bin/id -u`
    29            UID=`/usr/bin/id -ru`
    30        fi
    31        USER="`/usr/bin/id -un`"
    32        LOGNAME=$USER
    33        MAIL="/var/spool/mail/$USER"
    34    fi
    35    
    36    # Path manipulation
    37    if [ "$EUID" = "0" ]; then
    38        pathmunge /usr/sbin
    39        pathmunge /usr/local/sbin
    40    else
    41        pathmunge /usr/local/sbin after
    42        pathmunge /usr/sbin after
    43    fi
    44    
    45    HOSTNAME=`/usr/bin/hostname 2>/dev/null`
    46    HISTSIZE=1000
    47    if [ "$HISTCONTROL" = "ignorespace" ] ; then
    48        export HISTCONTROL=ignoreboth
    49    else
    50        export HISTCONTROL=ignoredups
    51    fi
    52    
    53    export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL
    54    
    55    # By default, we want umask to get set. This sets it for login shell
    56    # Current threshold for system reserved uid/gids is 200
    57    # You could check uidgid reservation validity in
    58    # /usr/share/doc/setup-*/uidgid file
    59    if [ $UID -gt 199 ] && [ "`/usr/bin/id -gn`" = "`/usr/bin/id -un`" ]; then
    60        umask 002
    61    else
    62        umask 022
    63    fi
    64    
    65    for i in /etc/profile.d/*.sh /etc/profile.d/sh.local ; do
    66        if [ -r "$i" ]; then
    67            if [ "${-#*i}" != "$-" ]; then 
    68                . "$i"
    69            else
    70                . "$i" >/dev/null
    71            fi
    72        fi
    73    done
    74    
    75    unset i
    76    unset -f pathmunge
    77    
    78    #Add by yinzhengjie
    79    JAVA_HOME=/home/softwares/jdk1.8.0_201
    80    PATH=$PATH:$JAVA_HOME/bin
    81    
    82    
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# cat -n /etc/profile        #注意观察第67行就用到咱们这里说的"$-"变量哟~

2>.脚本安全

-u: 
  在扩展一个没有设置的变量时,显示错误信息   等同set
-o nounset

-e:
  如果一个命令返回一个非0退出状态值(失败)就退出   等同set
-o errexit
[root@node101.yinzhengjie.org.cn ~]# vim shell/test.sh
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# cat -n shell/test.sh
     1    #!/bin/bash
     2    #
     3    #********************************************************************
     4    #Author:        yinzhengjie
     5    #QQ:             1053419035
     6    #Date:             2019-11-21
     7    #FileName:        test.sh
     8    #URL:             http://www.cnblogs.com/yinzhengjie
     9    #Description:        The test script
    10    #Copyright notice:     original works, no reprint! Otherwise, legal liability will be investigated.
    11    #********************************************************************
    12    
    13    set -u          #在扩展一个没有设置的变量时,显示错误信息
    14    DIR=/tmp
    15    unset DIR       #此处为我们故意将变量名称删除掉,让下一行指令引用时找不到该变量
    16    rm -rf $DIR/test/*
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# bash shell/test.sh
shell/test.sh: line 16: DIR: unbound variable
[root@node101.yinzhengjie.org.cn ~]# 
"-u"使用案例
[root@node101.yinzhengjie.org.cn ~]# vim shell/test.sh
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# cat shell/test.sh
#!/bin/bash
#
#********************************************************************
#Author:        yinzhengjie
#QQ:             1053419035
#Date:             2019-11-21
#FileName:        test.sh
#URL:             http://www.cnblogs.com/yinzhengjie
#Description:        The test script
#Copyright notice:     original works, no reprint! Otherwise, legal liability will be investigated.
#********************************************************************

set -ue           #"-e"表示如果一个命令返回一个非0退出状态值(失败)就退出当前脚本,即不会继续执行脚本.
xxx
ls
cat /etc/profile
DIR=/tmp
rm -rf $DIR/test/*
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# bash shell/test.sh
shell/test.sh: line 14: xxx: command not found
[root@node101.yinzhengjie.org.cn ~]# 
"-e"选项使用案例

 

七.小试牛刀
(1)让所有用户的PATH环境变量的值多出一个路径,例如:/usr/local/apache/bin
(2)用户 root 登录时,将命令指示符变成红色,并自动启用如下别名: 
    rm=‘rm –i’     cdnet=‘cd /etc/sysconfig/network-scripts/’     editnet=‘vim /etc/sysconfig/network-scripts/ifcfg-eth0’     editnet=‘vim /etc/sysconfig/network-scripts/ifcfg-eno16777736 或 ifcfg-ens33 ’ (如果系统是CentOS7) (3)任意用户登录系统时,显示红色字体的警示提醒信息“Hi,dangerous!” (4)编写生成脚本基本格式的脚本,包括作者,联系方式,版本,时间,描述等 (5)编写用户的环境初始化脚本reset.sh,包括别名,登录提示符,vim的设置,环境变量等
 
 

以上是关于shell中的循环语法的主要内容,如果未能解决你的问题,请参考以下文章

将vscode打造成无敌的IDE打造shell IDE--三大神器

Shell编程Shell中for循环while循环until循环语句

Shell编程Shell中for循环while循环until循环语句

shell中的for循环出现语法错误(syntax error: bad for loop variable)

在下面的代码片段中的剩余 ='passthrough' 处的代码中出现语法错误

shell if 语句