Shell 变量、字符串与数组基础
helloworld
以下为 Bash 示例,未执行。先在独立目录创建 helloworld.sh,只保存下面源码:
#!/bin/bash
# #! 指定直接执行时的解释器;# 开始 Bash 注释。
echo "Hello World !"再执行(命令不是脚本源码的一部分):
chmod +x ./helloworld.sh
./helloworld.sh预期标准输出:
Hello World !Shell 变量
命名规则
- 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
- 中间不能有空格,可以使用下划线(_)。
- 不能使用标点符号。
- 不能使用 bash 里的关键字(可用 help 命令查看保留关键字)。
操作
- 创建使用shell
#!/bin/bash user_name="lcc" age=23 sex="男" echo $user_name echo $age # 建议使用${变量名} # 为了帮助解释器识别变量的边界 :<<EOF echo "I am good at ${skill}Script" EOF echo ${sex} - 只读
#!/bin/bash
user_name="lcc"
readonly user_name
user_name="Cc"
echo ${user_name}预期赋值行报 readonly variable;原值仍为 lcc。错误与标准输出分属不同流,不保证显示顺序一致。
- 删除
#!/bin/bash
user_name="lcc"
unset user_name
echo ${user_name}运行结果 什么都不会输出,建议提示变量不存在
- 变量类型 运行 shell 时,会同时存在三种变量:
- 局部变量 局部变量在脚本或命令中定义,仅在当前 shell 实例中有效,其他 shell 启动的程序不能访问局部变量。
- 环境变量 通过 export 导出的变量会传给之后启动的子进程;并非任意已运行程序都能访问当前 Shell 的变量,有些程序需要环境变量来保证其正常运行。必要的时候 shell 脚本也可以定义环境变量。
- shell 变量 shell 变量是由 shell 程序设置的特殊变量。shell 变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了 shell 的正常运行
字符串
单引号与双引号
- 单引号
#!/bin/bash
name='C\sadf@$@#!$@#@#!c\'
echo ${name}
url='"lichaoche's'ng.top"'
echo ${url}预期输出(未执行):
C\sadf@$@#!$@#@#!c\
"lichaochesng.top"- 双引号
#!/bin/bash
name='Cc'
str="Hello, I know you are \"${name}\"! \n"
printf '%b' "$str"预期输出:
Hello, I know you are "Cc"!- 区别
- 单引号
- 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的
- 单引号字串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用
- 双引号
- 双引号里可以有变量
- 双引号里可以出现转义字符
- 单引号
字符串操作
- 拼接
#!/bin/bash
your_name="Cc"
# 使用双引号拼接
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting $greeting_1
# 使用单引号拼接
greeting_2='hello, '$your_name' !'
greeting_3='hello, ${your_name} !'
echo $greeting_2 $greeting_3预期输出(未执行):
hello, Cc ! hello, Cc !
hello, Cc ! hello, ${your_name} !获取长度
shell#!/bin/bash name="CcAndHyperAndLccAndChaoChengLi" echo ${#name} #输出 30 sex="Male" echo ${#sex} # 输出 4提取字符串
shell#!/bin/bash name="lcc" # 0 开始计算 echo ${name:0:2} #输出 lc echo ${name:1:2} #输出cc echo ${name::2} #输出 lc查找字符串
#!/bin/bash name="lcc shell" # 哪个字母先出现就计算哪个 echo `expr index "${name}" l` #输出 1 ps:为什么查找从1开始计算 echo `expr index "${name}" e` #输出 7
ps:是 ` 不是 '
数组
创建、查看、获取、修改、[二维数组....]
#!/bin/bash
# 数组没有逗号分隔
arrayName=("lcc" "Cc" "Hyper" 10)
arrayAge=(
23
18
6
)
# 下面查看数组
echo ${arrayName[1]} #输出 Cc
echo ${arrayAge[1]} #输出 18
# 获取所有元素
echo ${arrayName[@]} #输出 lcc Cc Hyper 10
# 数组长度
length=${#arrayName[@]}
echo ${length} #输出 4
echo ${#arrayAge[*]} #输出 3
# 通过下标修改元素
arrayName[0]="yes"
echo ${arrayName[@]} #yes Cc Hyper 10
#--------
# 二维数组
# https://www.jianshu.com/p/543fa9df3469
# https://www.cnblogs.com/wyf-349/p/11236939.html
#--------传递参数
#!/bin/bash
echo "运行时参数传递";
echo "执行的文件名:$0";
echo "第一个参数为:$1";
echo "第二个参数为:$2";
echo "第三个参数为:$3";
echo "参数个数:$#"
echo "传递的参数作为一个字符串显示:$*"
echo "-- \$* 演示 ---"
for i in "$*"; do
echo $i
done
echo "-- \$@ 演示 ---"
for i in "$@"; do
echo $i
done运行 ./demo1.sh lcc 23 M,以下为原记录输出(非本轮执行):
运行时参数传递
执行的文件名:./demo1.sh
第一个参数为:lcc
第二个参数为:23
第三个参数为:M
参数个数:3
传递的参数作为一个字符串显示:lcc 23 M
-- $* 演示 ---
lcc 23 M
-- $@ 演示 ---
lcc
23
M区别
- #$* 与 $@ 区别:
- 相同点:都是引用所有参数。
- 不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数 1、2、3,,则 " * " 等价于 "1 2 3"(传递了一个参数),而 "@" 等价于 "1" "2" "3"(传递了三个参数)。
运算符
以下用就地 Bash 例说明运算符,未执行;原图片与历史仓库文件仍保留。
算术运算符
printf '%s\n' "$((2 * 3))" 预期输出 6。

原仓库代码路径:operator/t2.sh,位于页首 GitHub 链接;本页未包含其源码。 注意:
- 外部
expr的乘号需引用或转义,避免 Shell 先展开为文件名;Bash 算术展开$((2 * 3))中无需转义。 - if...then...fi 是条件语句,后续将会讲解。
$((表达式))是 Shell 算术展开,与操作系统是否为 macOS 无关,不是另一种 expr 语法。
关系运算符
[ 3 -gt 2 ] 比较整数大小,预期状态 0;它不输出 true 字符串。

原仓库代码路径:operator/t3.sh,位于页首 GitHub 链接;本页未包含其源码。
布尔运算符
[ -n "$value" ] 检查非空;! 可以对一个命令的成功状态取反。

原仓库代码路径:operator/t4.sh,位于页首 GitHub 链接;本页未包含其源码。
逻辑运算符
cmd1 && cmd2 仅在前者成功时执行后者;cmd1 || cmd2 仅在前者失败时执行后者。

原仓库代码路径:operator/t5.sh,位于页首 GitHub 链接;本页未包含其源码。
字符串运算符
[ "$name" = "Cc" ] 比较两个字符串,参数须引用。

原仓库代码路径:operator/t6.sh,位于页首 GitHub 链接;本页未包含其源码。
文件检测运算符
[ -f "$path" ] 检查是否指向普通文件;这不证明所有者、权限或路径没有链接。

原仓库代码路径:operator/t7.sh,位于页首 GitHub 链接;本页未包含其源码。
继续阅读
- 命令与系统观察
- 命令与系统观察
- 应用实践