基础


只读变量

  1. var=3
  2. readonly var
  3. readonly var=3
  • 不可修改
  • 不可删除

删除变量

  1. unset var
  2. # unset -f f1 删除f1函数

字符串


定义形式

  1. 'this is a string'
  2. "double quote string"
  • 单引号字符串中无法解析转义字符和变量,双引号可以

获取字符串长度

  1. string="hello"
  2. echo ${#string}

截取字符串

  1. #!/bin/bash
  2. #字符串截取
  3. var=http://www.aaa.com/123.htm
  4. echo ${var#*//} #从左边开始删除第一个//及左边的字符
  5. echo ${var##*/} #从左边开始删除最后一个字符
  6. echo ${var%/*} #从右边开始删除第一个, 保留左边内容
  7. echo ${var%%/*} #从右边开始删除最后一个
  8. echo ${var:0:5} #左边开始保留字符个数
  9. echo ${var:7} #从左边第7个开始,保留到结尾的字符
  10. echo ${var:0-7:3} #从右边开始,保留的字符个数
  11. echo ${var:0-7} #从右边开始,保留到结束
  12. echo $var

查找字符串

  1. string="runoob is a great site"
  2. echo `expr index "$string" io` # 输出 4

scope

三种作用域的变量

  1. 只能在函数内部使用的变量称为局部变量

    1. #!/bin/bash
    2. func1(){
    3. local var1="str"
    4. echo $var1
    5. # "str"
    6. }
    7. func1
    8. echo $var1
    9. # ""
  2. 可以在当前会话中使用的变量称为全局变量, 一般在shell或命令行中定义的变量

    在脚本中使用其它脚本文件需使用”. 文件名”或”export 文件名”, 这样其它脚本文件中的变量才会在当前进程中有效;这是因为脚本中嵌套脚本相当于开子进程运行其它脚本文件。

  3. 对当前进程和子进程有效的变量称为环境变量

    export var可以将变量导出为环境变量,对当前进程和子进程都有效 注意子进程修改变量对父进程变量无效

要想变量对所有进程都有效,可以将其写入到配置文件当中,所有进程在启动时都会读取该配置文件。

环境变量

在内存中存储数据, 分为全局变量和局部变量

全局变量:
所有shell会话可见

printenv查看全部
env 查看全部
printenv HOME 查看单个变量

局部变量:
set命令查看所有的环境变量,包括局部变量,全局变量和用户定义变量

设置用户定义变量

局部变量 : 直接 var=value
有效期: 当前shell会话

全局变量:
var=value
export value
有效期: shell和shell子会话
注: 修改子shell中全局变量不会影响到父shell全局变量的值


删除环境变量

unset var
子shell中删除全局环境变量不会影响父全局变量


设置PATH环境变量

描述: 在启动shell时会加载若干个文件,这里面对环境变量的设置一直有效
查看 echo $PATH
添加: PATH=$PATH:/usr/bin

环境变量持久化,在文件中增加环境变量, 检查的启动文件与启动bash shell的方式有关

  • 登录时默认shell
  • 非登录shell的交互式shell
  • 运行脚本的非交互式shell

登录shell

检查的文件一般有:

  • /etc/profile
  • $HOME/.bash_profile
  • $HOME/.bashrc
  • $HOME/.bash_login
  • $HOME/.profile

    解释: /etc/profile为每个用户登录都会执行的文件

  1. # /etc/profile
  2. # System wide environment and startup programs, for login setup
  3. # Functions and aliases go in /etc/bashrc
  4. # It's NOT a good idea to change this file unless you know what you
  5. # are doing. It's much better to create a custom.sh shell script in
  6. # /etc/profile.d/ to make custom changes to your environment, as this
  7. # will prevent the need for merging in future updates.
  8. pathmunge () {
  9. #case语句匹配
  10. case ":${PATH}:" in
  11. *:"$1":*)
  12. ;;
  13. *)
  14. if [ "$2" = "after" ] ; then
  15. PATH=$PATH:$1
  16. else
  17. PATH=$1:$PATH
  18. fi
  19. esac
  20. }
  21. if [ -x /usr/bin/id ]; then
  22. if [ -z "$EUID" ]; then
  23. # ksh workaround
  24. EUID=`/usr/bin/id -u`
  25. UID=`/usr/bin/id -ru`
  26. fi
  27. USER="`/usr/bin/id -un`"
  28. LOGNAME=$USER
  29. MAIL="/var/spool/mail/$USER"
  30. fi
  31. # Path manipulation root用户加上以下变量
  32. if [ "$EUID" = "0" ]; then
  33. pathmunge /usr/sbin
  34. pathmunge /usr/local/sbin
  35. else
  36. pathmunge /usr/local/sbin after
  37. pathmunge /usr/sbin after
  38. fi
  39. HOSTNAME=`/usr/bin/hostname 2>/dev/null`
  40. HISTSIZE=1000 #命令历史记录
  41. if [ "$HISTCONTROL" = "ignorespace" ] ; then
  42. export HISTCONTROL=ignoreboth
  43. else
  44. export HISTCONTROL=ignoredups
  45. fi
  46. export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL
  47. # By default, we want umask to get set. This sets it for login shell
  48. # Current threshold for system reserved uid/gids is 200
  49. # You could check uidgid reservation validity in
  50. # /usr/share/doc/setup-*/uidgid file
  51. # 设定文件权限掩码
  52. if [ $UID -gt 199 ] && [ "`/usr/bin/id -gn`" = "`/usr/bin/id -un`" ]; then
  53. umask 002
  54. else
  55. umask 022
  56. fi
  57. for i in /etc/profile.d/*.sh /etc/profile.d/sh.local ; do
  58. if [ -r "$i" ]; then
  59. if [ "${-#*i}" != "$-" ]; then
  60. . "$i"
  61. else
  62. . "$i" >/dev/null
  63. fi
  64. fi
  65. done
  66. unset i
  67. unset -f pathmunge

if [ “${-#i}” != “$-“ ]; 解释如下: $- 表示shell标志如himBH ${-#i} 在$-中去掉*i的最小前缀 举例 如 x=$HOME/src/cmd; echo “${x#$HOME}” #返回/src/cmd 于是该语句的含义表示当环境是在登录shell当中则执行 因为$- 为himBH

整理一下: 导出各种环境变量和设置文件权限掩码, 读取/etc/profile.d中sh文件执行

$HOME/.bash_profile

  1. # .bash_profile
  2. # Get the aliases and functions
  3. if [ -f ~/.bashrc ]; then
  4. . ~/.bashrc #加载.bashrc文件
  5. fi
  6. # User specific environment and startup programs
  7. PATH=$PATH:$HOME/bin
  8. export PATH

$HOME/.bashrc

  1. # .bashrc
  2. # User specific aliases and functions
  3. alias rm='rm -i'
  4. alias cp='cp -i'
  5. alias mv='mv -i'
  6. # Source global definitions
  7. if [ -f /etc/bashrc ]; then
  8. . /etc/bashrc
  9. fi

总结:

  1. 首先系统加载/etc/profile文件, 设置基本的环境变量和加载/etc/profile.d/中的shell文件
  2. 系统按顺序查找$HOME/.bash_profile, $HOME/.bash_login和$HOME/.profile文件, 并执行第一个找到的文件并执行$HOME/.bashrc文件
  3. $HOME/.bashrc文件设置命令别名并执行/etc/bashrc文件

交互式shell进程

非登录系统启动如bash启动时该shell称为交互式shell, 交互式shell会加载$HOME/.bashrc文件

非交互式shell

执行脚本使用的shell.关键是BASH_ENV环境变量检测启动的文件

变量属性


变量属性 i r a x f

  • i 声明整型变量, 可直接用于加减
  • r readonly只读变量
  • a 数组
  • f 函数

语法:

  1. declare [+/-][rxi][变量名称=设置值] declare -f
  • +/- “-“设置变量的属性, “+”取消变量的属性
  • -f 仅显示函数(不理解)
  • r 只读变量
  • x 变量成为环境变量
  • i [设置值]数值, 字符串或运算式

示例:

  1. #!/bin/bash
  2. declare -i ab
  3. ab=56
  4. echo $ab #56
  5. ab="ef"
  6. echo $ab #0
  7. declare +i ab
  8. ab="ef"
  9. echo $ab #ef
  10. declare -r ab=77
  11. ab=88 # 不可修改
  12. echo $ab #77
  13. declare -a cd='([0]="a" [1]="b" [2]="c")'
  14. echo "${cd[@]}" # a b c
  15. # declare -f f1
  16. # f1=3
  17. # echo $f1
  18. declare -f
  19. f1(){
  20. echo '123'
  21. }
  22. f1
  23. f2=3
  24. echo $f2