Bash 变量操作

Bash 变量操作_第1张图片

Bash 是 Unix shell 的一种,本文讨论的是 Bash,而不一定是/bin/sh 所链接的那个 shell。
这里出现的所有代码片段,默认在顶上都添加了#!/bin/bash

1. 严格意义上的 Bash 变量类型

Bash 变量只有两种类型,字符串和数组。

不过从严格意义上,Bash 没有变量类型。Bash 中的变量,在运行的时候会被展开成其对应的值(字符串)。你可以把它看做 C/C++中的宏定义,或者一些模板语言中的占位符。

一般情况下,变量通过=赋值,注意=两边不要留空格
要想访问变量,只需在变量名前面添加$,解释器就会对它进行展开,养成加{}的好习惯。如果该变量并不存在,解释器会把它展开成“”。

who=spacewander
echo $me
echo $who

2. 命令行参数

我们可以在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:$nn 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推……
注意:$0获取的脚本的名字(其实就是其他语言中的第 0 个参数)

在 Bash 中,使用$1可以获取命令行输入的第一个参数,$2可以获取命令行输入的第 2 个参数,$3可以获取命令行输入的第…
你看,$1到$10000 的用法就这么交代完了。Bash 还是挺有逻辑的嘛。

$@获取所有的参数,$#获取参数的数目。
@#这两个符号,前者表示全部参数,后者表示参数的数目。

参数处理 说明
$n 第几个参数,n 代表一个数字,$0表示命令本身,$1 即第一个参数,依次类推
$# 传递到脚本的参数个数
$* 以一个单字符串显示所有向脚本传递的参数。 如"$*“用「”」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。
$$ 脚本运行的当前进程 ID 号
$! 后台运行的最后一个进程的 ID 号
$@ ∗ 相同,但是使用时加引号,并在引号中返回每个参数。如 " *相同,但是使用时加引号,并在引号中返回每个参数。 如" 相同,但是使用时加引号,并在引号中返回每个参数。如"@“用「”」括起来的情况、以"$1" “$2” … “$n” 的形式输出所有参数。
$- 显示 Shell 使用的当前选项,与set 命令功能相同。
$? 显示最后命令的退出状态。0 表示没有错误,其他任何值表明有错误。

3. 数组和关联数组

Bash 中可以使用两种容器。
一种是数组,另一种是关联数组,类似于其他语言中的 Map/Hash/Dict。
声明数组的常用语法: declare -a ARY或者ARY=(1 2 3)
声明关联数组的唯一语法: declare -A MAP

赋值的语法:
直接ARY[N]=VALUE,N 可以是数字索引也可以是键。关联数组可以使用MAP=([x]=a [y]=b)进行多项赋值,注意这是赋值的语句而不是声明。
亲测数组中的索引不一定要按顺序来,你可以先给 2 和 3 上的元素赋值。(同样算是弱类型的 Javascript 也支持这种无厘头赋值,这算通病么?)

往现有数组批量添加元素:

ARY+=(a b c)
MAP+=([a]=1 [b]=2)

取值:

${ARY[INDEX]}
${MAP[KEY]}

注意花括号的使用

${A[@]}` 展开成所有的变量,而获取数组长度使用 `${#A[@]}

切片:

${ARY[@]:N:M}

N 是 offset 而 M 是 length

返回索引,相当于 keys():

${!MAP[@]}

试试下面的代码:

declare -a ARY
declare -A MAP
MAP+=([a]=1 [b]=2)
ARY+=(a b c)

echo ${ARY[1]}
echo ${MAP[a]}
echo "${ARY[@]}"
echo "${MAP[@]}"
echo "${ARY[@]:0:1}"
echo ${#ARY[@]}
echo "${!MAP[@]}"

ARY[4]=a
echo ${ARY[@]}
echo ${ARY[3]}

4. 变量(字符串)变换

Bash 中的变量变换,大体是${变量[操作符]}的形式

4.1 大小写变换

HI=HellO

echo "$HI" # HellO
echo ${HI^} # HellO
echo ${HI^^} # HELLO
echo ${HI,} # hellO
echo ${HI,,} # hello
echo ${HI~} # hellO
echo ${HI~~} # hELLo

^大写,,小写, ~大小写切换
重复一次只修改首字母,重复两次则应用于所有字母。

混着用会怎样?

echo ${HI^,^} # HellO

看来是不行的 ×_×

4.2 移除匹配的字符串

%xx 从后往前,开始匹配,移除匹配的内容
%%xx 跟上面的差不多,不过这是贪婪匹配
#xx 从前往后,开始匹配,移除匹配的内容
##xx 跟上面的差不多,不过这是贪婪匹配

这个比较难理解,不过看下面几个例子应该能明白了。

FILENAME=/home/spacewander/param.sh
echo ${FILENAME%/*} # /home/spacewander
echo ${FILENAME%%/*} #
echo ${FILENAME#*/} # home/spacewander/param.sh
echo ${FILENAME##*/} # param.sh

4.3 查找并替换

/MATCH/VALUE 替换第一个匹配的内容。
//MATCH/VALUE 替换匹配的内容

echo ${FILENAME/home/office} # /office/spacewander/param.sh
echo ${FILENAME//s/S} # /home/Spacewander/param.Sh

4.4 其它字符串操作

获取变量(字符串)长度:

${#FILENAME}

字符串切片:跟数组切片是同样的语法:

${STR:offset:len}

你还可以使用负数作为 offset,这时候就是从后往前算起。注意负数要用括号括起来,避免冲突。

TEXT=这个程序充满了BUG!
echo ${TEXT:0:8}
echo ${TEXT:4}
echo ${TEXT:(-4)}

4.5 关于变量,其它的内容

Bash 中有一项特性,你可以方便地检查某个变量是否设置了,如果没有设置,就赋予一个默认值。尤其在处理环境变量的时候,这项特性会让你感到欣慰。
语法是${VAR:=VALUE}或者${VAR=VALUE}。此外,还有一个相似的语法,${VAR:-VALUE}${VAR-VALUE}

下面展示下两者的区别

# expand to default variable
echo ${NULL-"Not null"} # Not null
echo ${NULL} #

# set default variable
echo ${NIL="Not nil"} # Not nil
echo ${NIL} # Not nil

可以看出,前者只是当变量不存在时,展开成指定的值。而后者在变量不存在时,将变量的值设置为指定值。

最后介绍一个,当目标变量不存在时,指定报错信息的语法。

echo ${TARGET?Not Found} # 当$TARGET不存在时,显示TARGET: Not Found,并结束程序。

【星猿科技】:在这里我们共同探索科技新趋势,分享积累的点滴,从人工智能到高性能计算,我们追求技术的进步,同时珍视分享的力量。欢迎关注我们,在科技与影视的精彩世界中一起遨游,发现更多未知!

你可能感兴趣的:(SHELL编程,bash,linux,程序人生)