特点:1 shell变量没有数据类型的区分

   2 Shell 把任何存储在变量中的值,皆视为以字符组成的“字符串”。

     3  设定的变量值只在当前shell环境中有作用

     4   不能以数字开头

     5   =号两边不能存在空格

     6  若变量值中存在空格,必须用括号将变量值括起来   I = “Jack  Black”

在编写shell时,如果变量未赋值,后续使用时不会出现任何错误。如果要显示错误提示,则需要命令  shopt -s -o nounset 

shopt -s -o nounset解析如下

 

 

.范例如下

[root@localhost ~]# vim test1.sh
#!/bin/bash
echo $Infomix
[root@localhost ~]# sh test1.sh
                                                # 未提示任何错误
[root@localhost ~]# vim test1.sh            
[root@localhost ~]# vim test1.sh
#!/bin/bash
shopt -s -o nounset   #添加错误提示

echo $Infomix
[root@localhost ~]# sh test1.sh
test1.sh:行4: Infomix: 为绑定变量  #提示错误

 

二  取得变量值

$变量名称=${变量名称}

如果变量作为字符的一部分输出时,则必须用${}将变量括起来,否则shell将无法识别变量。$会将后面的所有字符当做变量的一部分,肯定是找不到变量的

[root@localhost ~]# myname='lsq'
[root@localhost ~]# echo $myname
lsq
[root@localhost ~]# echo ${myname}
lsq
[root@localhost ~]# echo hello${myname}boy
hellolsqboy
[root@localhost ~]# echo hello$mynameboy
hello

如果后面接的不是字符,也不是_下划线,则不需要{}来括起来。变量后接中文也是可以的。呵呵。

[root@localhost ~]# dir2=sbin
[root@localhost ~]# echo /usr/local/$dir2/config
/usr/local/sbin/config

$是去变量值的特殊字符,如果要显示$怎么操作,转义字符 \  或者用单引号括起来   '$i'

Bash除了echo之外,还提供了一个c类似的printf的语法。感觉这个东西有字符串格式化的意思。体会一下

%s  以字符串的形式显示变量值

[root@localhost ~]# printf "%s" "$dir2"
sbin[root@localhost ~]# printf "%s\n" "$dir2" 
sbin                              #\n和c语言一样,都是换行的意思。
[root@localhost ~]# 
[root@localhost ~]# SP='ABC 123 XYZ'
[root@localhost ~]# printf "%q\n" "$SP"
ABC\ 123\ XYZ   #%q会将变量值中的特殊字符,用\字符转义,实例中就是在空格前加\

 

三  取消与清空变量

unset 变量名

unset -v  变量名       -v 表示取消的是变量

unset -f 函数名  -f 表示取消的是函数

清空变量值    

变量名=        跟unset的区别是,清空变量值,该变量还存在,只不过值变成空而已。unset则会将变量销毁

四    变量和引号

双引号和单引号的区别

前边说过,变量赋值可以用单引号或者双引号,但是二者是有区别的

双引号相对于单引号可以有如下操作

1 替换变量             例

[root@localhost shellscript]# vim test2.sh
#! /bin/bash

shopt -s -o nounset
myname="Bash shell"
#echo $myname
hello="hello ,i am $myname"
echo $hello
[root@localhost shellscript]# sh test2.sh 
hello ,i am Bash shell    #将变量名myname用Bash shell 进行了替换
#但是如果我们用单引号

[root@localhost shellscript]# vim test2.sh
#! /bin/bash


shopt -s -o nounset
myname="Bash shell"
#echo $myname
#hello="hello ,i am $myname"
hello='hello ,i am ,$myname'
echo $hello


[root@localhost shellscript]# sh test2.sh
hello ,i am ,$myname   #看到了么?他不会替换,他会将变量名整体输出

 如果要在双引号中输出变量名而非替换,则需要用到\转义字符转义

2 替换命令执行结果

3 替换算数运算结果

 四   变量的有效范围

变量的有效范围就是当前所处的shell环境

如果要让变量在所有的shell都执行,那就需要将该变量设置成环境变量

通过  export 命令就可以将变量设置成环境变量。 

export testVar="hello world"
或
testVar="hello world"
export testVar

取消环境变量

testVar=
或者
unset testVar

 

五  Bash 的内置变量

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 六  设置只读变量

readonly 命令和declare -r 命令

readonly 或  readonly -p     列出只读属性的变量列表

readonly -f  函数名       设置该函数不可修改

readonly -a 数组变量        设置后该数组为只读数组

s[0]=10
s[1]=20
s[2]=30

readonly -a s     #设置该数组为只读数组

s[3]=50            该行 会报错

调整变量的其他属性

 

 

[root@localhost ~]# declare -i I=60  #设定该变量为整数变量
[root@localhost ~]# echo $I
60
[root@localhost ~]# I="test"     #如果传入字符串,则会将该变量变为0
[root@localhost ~]# echo $I
0
[root@localhost ~]# 

 

七   取别名

alias   变量名

[root@localhost ~]# alias -p   #列出别名列表
alias cp='cp -i'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l.='ls -d .* --color=auto'
alias ll='ls -l --color=auto'
alias ls='ls --color=auto'
alias mv='mv -i'
alias perlll='eval `perl -Mlocal::lib`'
alias rm='rm -i'
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'

 

alias  别名=指令            注意:=号两边不允许有空格。    如需要有空格,必须用括号括起来。如上例中alias l.='ls -d .*'    

 

unalias  取消别名

八   自定义工作环境

以一般账号的角色工作时,默认的工作环境配置文件为

 

 这里的~目录,一般指的是家目录

自定义工作环境的意义:让用户登录主机时,能拥有安全及易于执行命令的环境。包括  建立文件的权限  命令搜寻路径  环境变量 命令提示符 别名  喜好比较器   显示文件使用的颜色等

[root@localhost ~]# cd /root
[root@localhost ~]# cat .bash_profile   #这个是root的默认配置文件
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
        . ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:$HOME/bin

export PATH
[root@localhost /]# cd home   #这个是普通用户的配置文件,普通用户在家目录 /home目录中
[root@localhost home]# ls
ftptest  lsq
[root@localhost home]# cd lsq
[root@localhost lsq]# cat .bash_profile
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
        . ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:$HOME/.local/bin:$HOME/bin

export PATH

管理员维护的环境配置文件一般有三个   /etc/profile     /etc/bashrc  /etc/skel目录下的文件

其中  /etc/profile和/etc/bashrc中的设定,会影响所有账号的使用环境。

在/etc/profile中,通常会设定 umask,PATH,多国语言环境,提示符号,别名等

这是我本机的profile

[root@localhost etc]# cat profile
# /etc/profile

# System wide environment and startup programs, for login setup
# Functions and aliases go in /etc/bashrc

# It's NOT a good idea to change this file unless you know what you
# are doing. It's much better to create a custom.sh shell script in
# /etc/profile.d/ to make custom changes to your environment, as this
# will prevent the need for merging in future updates.

pathmunge () {
    case ":${PATH}:" in
        *:"$1":*)
            ;;
        *)
            if [ "$2" = "after" ] ; then
                PATH=$PATH:$1
            else
                PATH=$1:$PATH
            fi
    esac
}


if [ -x /usr/bin/id ]; then
    if [ -z "$EUID" ]; then
        # ksh workaround
        EUID=`/usr/bin/id -u`
        UID=`/usr/bin/id -ru`
    fi
    USER="`/usr/bin/id -un`"
    LOGNAME=$USER
    MAIL="/var/spool/mail/$USER"
fi

# Path manipulation
if [ "$EUID" = "0" ]; then
    pathmunge /usr/sbin
    pathmunge /usr/local/sbin
else
    pathmunge /usr/local/sbin after
    pathmunge /usr/sbin after
fi

HOSTNAME=`/usr/bin/hostname 2>/dev/null`
HISTSIZE=1000
if [ "$HISTCONTROL" = "ignorespace" ] ; then
    export HISTCONTROL=ignoreboth
else
    export HISTCONTROL=ignoredups
fi

export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL

# By default, we want umask to get set. This sets it for login shell
# Current threshold for system reserved uid/gids is 200
# You could check uidgid reservation validity in
# /usr/share/doc/setup-*/uidgid file
if [ $UID -gt 199 ] && [ "`/usr/bin/id -gn`" = "`/usr/bin/id -un`" ]; then
    umask 002
else
    umask 022
fi

for i in /etc/profile.d/*.sh /etc/profile.d/sh.local ; do
    if [ -r "$i" ]; then
        if [ "${-#*i}" != "$-" ]; then 
            . "$i"
        else
            . "$i" >/dev/null
        fi
    fi
done

unset i
unset -f pathmunge

一下是本机普通用户的配置环境,在/etc/skel目录中

[root@localhost ~]# cd /etc/skel
[root@localhost skel]# ls
[root@localhost skel]# ls -la
总用量 28
drwxr-xr-x.   3 root root    78 4月  11 2018 .
drwxr-xr-x. 162 root root 12288 10月 14 15:36 ..
-rw-r--r--.   1 root root    18 10月 31 2018 .bash_logout
-rw-r--r--.   1 root root   193 10月 31 2018 .bash_profile
-rw-r--r--.   1 root root   231 10月 31 2018 .bashrc
drwxr-xr-x.   4 root root    39 8月  19 11:00 .mozilla
[root@localhost skel]# cat .bash_profile
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
        . ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:$HOME/.local/bin:$HOME/bin

export PATH
[root@localhost skel]# cat .bashrc
# .bashrc

# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi

# Uncomment the following line if you don't like systemctl's auto-paging feature:
# export SYSTEMD_PAGER=

# User specific aliases and functions
[root@localhost skel]# cat .bash_logout
# ~/.bash_logout

 

 

九  数组

bash数组的特点:   1   没有个数限制    2 可以跳跃赋值   3 所以可以表达式表示,如1+2      4  bash只支持一维数组

[root@localhost ~]# A[0]=5
[root@localhost ~]# A[1]=10
[root@localhost ~]# A[2]=28
[root@localhost ~]# A[3]="bash shell"

 [root@localhost ~]# echo $A
  5

[root@localhost ~]# echo $A[0]    看出跟上一句的区别了么?他走的是C语言的路子,读取$A直接取得是数组首地址的值,如果要取数组剩余标的值,就需要下面的操作.也就是将整个数组包含小标用大括号括起来,表示一个整体变量,用$读出
5[0]
[root@localhost ~]# echo $(A[0])    
bash: A[0]: 未找到命令...

[root@localhost ~]# echo ${A[0]}      #这里要注意一下,取数组值的时候,用到的是{}大括号
5
[root@localhost ~]# echo ${A[1+1]}
28
[root@localhost ~]# B={23 88 99 66}
bash: 88: 未找到命令...
[root@localhost ~]# B=(23 88 99 66)      #数组群体赋值的时候,用到的是()小括号。这点要注意
[root@localhost ~]# echo ${B[0]}
23

 正因为,shell数组没有个数的限制,也就是说,不需要在使用数组的时候,首先要固定一下数组的长度,所以,他的自由度很大,可以给某一下标无限,跳跃似的赋值

取出所有数组元素 

用@符号来代替数组下标

[root@localhost ~]# echo ${A[@]}
5 10 28 bash shell

取得数组个数 

${#A[@]}的格式来取得数组的小标

[root@localhost ~]# echo ${#A[@]}
4

如果数组某个下标表示的值为字符串,还可以取得该字符串的长度

${#A[索引]}

如上例中,A【3】的值是bash shell。我们要想知道他的长度可以采用如下

[root@localhost ~]# echo ${#A[3]}
10

 

删除数组和删除变量函数都用的同一个命令。unset

如果要删除整个数组可以用   unset A

如果要删除数组中的某个赋值   unset A[3]   就会将bash shell 删除。我们来试一下

[root@localhost ~]# unset A[3]              #将第三个数组值删除
[root@localhost ~]# echo ${#A[3]}
0                          #数组长度变为0     
[root@localhost ~]# echo ${A[3]}     
                          #值变为空
[root@localhost ~]# echo ${A[@]}
5 10 28                      #打印所有变量的时候,也可以证明A[3]确实没有了
[root@localhost ~]# unset A          #取消掉整个数组A
[root@localhost ~]# echo ${A[@]}        #整个数组A确实取消掉了。没有数组元素了

[root@localhost ~]# 

 

十   Here Document 

bash 有一种特殊的程序区域。就是 Here Document,也可以用来设定变量。

语法为    命令   <<标记

[root@localhost ~]# wc -l << countline
> line1
> line2
> line3
> countline
3

Here Document也支持变量替换。在输入的内容中,如果有变量,bash会在转向前,将变量值进行替换

[root@localhost ~]# From="From: me@example.edu.cn"     #四个变量
[root@localhost ~]# To="To: you@example.edu.cn"
[root@localhost ~]# Subject="Subject: Hello world"
[root@localhost ~]# Msg="happy new year"
[root@localhost ~]# EM="20090310.txt"
[root@localhost ~]# cat > $EM <<here                  #进行转向
> $From
> $To
> $Subject
> 
> $Msg
> here
[root@localhost ~]# cat 20090310.txt
From: me@example.edu.cn
To: you@example.edu.cn
Subject: Hello world

happy new year

 

利用Here Document做多行批注

bash中,只支持单行注释,#来开头

利用Here Document来做多行批注,可以用:来操作    : <<DO-NOTHING      

第一行,第二行,第三行 DO-NOTHING

利用Here Document夹带私货

书中就有一个夹带私货的例子。他是用Here Document写了一个C程序,然后在编译执行他,以便达到不可告人的目的,看看他是咋写的

[root@localhost ShellScript]# vim create_prg.sh
#! /bin/bash

echo "正在产生hello.c。。。。"
echo
cat <<'EOF' >hello.c
#include <stdio.h>

int main()
{
        printf("Hello world!\n");
        return 0;
}
EOF

echo "编译hello.c........"
echo 
#编译Hello.c,并产生执行文件
gcc -o hello hello.c

#若编译成功,则运行
if [ $? -eq 0 ]; then
        echo "执行 hello....."
        echo
        ./hello
else
        echo '执行失败'
fi
"create_prg.sh" [新] 27L, 374C 已写入                         
[root@localhost ShellScript]# sh create_prg.sh
正在产生hello.c。。。。

编译hello.c........

执行 hello.....

Hello world!
[root@localhost ShellScript]# ls
20090310.txt  create_prg.sh  hello  hello.c

这样就可以动态编写c程序,动态执行。神不知鬼不觉。。。

 

posted on 2019-10-10 15:48  孤独斗士  阅读(4904)  评论(0编辑  收藏  举报