Shell字符串操作技巧及if语句使用
一、Shell字符串基础:三种定义方式的区别
在Shell中,字符串可以用单引号、双引号或不加引号定义,它们的核心区别在于变量解析和特殊字符处理。
1. 单引号 ' '
:原样输出,拒绝解析
- •
规则:所有字符(包括变量、转义符等)都会原样输出,不进行任何解析。
- •
限制:字符串内不能出现单引号(即使用``转义也不行)。
- •
示例:
n=74 str1='c.biancheng.net$n' # $n 被当作普通字符,不会解析为变量 echo $str1 # 输出:c.biancheng.net$n
2. 双引号 " "
:解析变量,允许灵活控制
- •
规则:会解析其中的变量(如
$n
会替换为变量值),但字符串中的**双引号需用\` 转义**(如
"`)。 - •
优势:既可以用变量,又能通过转义控制特殊字符。
- •
示例:
n=74 str2="shell \"Script\" $n" # 双引号内的 $n 被解析为变量值,\" 转义为普通双引号 echo $str2 # 输出:shell "Script" 74
3. 不加引号:变量解析但限制严格
- •
规则:和双引号类似,变量会被解析,但字符串中不能包含空格(空格会被视为分隔符,导致后续内容被误认为其他变量或命令)。
- •
风险:若字符串含空格,空格后的部分可能被错误解析。
- •
示例:
str3=c.biancheng.net$n # 变量 $n 被解析,但若字符串有空格(如 "a b"),则 "b" 会被当成新变量 echo $str3 # 输出:c.biancheng.net74
二、字符串操作实战
1. 获取字符串长度
使用 ${#字符串变量}
直接获取长度:
text="hello"
echo ${#text} # 输出:5(字符数,包括空格)
2. 字符串拼接:直接相连,无需运算符
Shell中拼接字符串只需将变量/字符串紧挨着写(中间不能有空格,除非用引号包裹):
name="shell"
url="http://c.biancheng.net/shell/"# 基础拼接(无空格)
str1=$name$url # 输出:shellhttp://c.biancheng.net/shell/# 含符号拼接(冒号需直接连接)
str1=$name":"$url # 输出:shell:http://c.biancheng.net/shell/# 双引号内可含空格(推荐可读性)
str2="$name $url" # 输出:shell http://c.biancheng.net/shell/
str3="$name:$url" # 输出:shell:http://c.biancheng.net/shell/# 变量后接固定字符串(用大括号明确变量边界)
str4="${name}Script:${url}Index.html" # 输出:shellScript:http://c.biancheng.net/shell/Index.html
3. 字符串截取:两种计数方式+两种定位方法
(1)从指定位置开始截取(需起始位置+长度)
- •
格式:
${字符串:起始位置:截取长度}
- •
起始位置:从左到右,从0开始计数(程序员习惯)。
- •
长度:可选,省略则截取到字符串末尾。
- •
- •
示例:
url="c.biancheng.net" echo ${url:2:9} # 从第2个字符(0-based)开始,取9个字符 → "biancheng" echo ${url:2} # 从第2个字符开始,取到末尾 → "biancheng.net"
(2)从右边开始截取(需起始位置+长度)
- •
格式:
${字符串:0-起始位置:截取长度}
- •
起始位置:从右到左,从1开始计数(符合常人习惯,最右字符是第1个)。
- •
长度:可选,省略则截取到末尾。
- •
- •
示例:
url="c.biancheng.net" echo ${url:0-13:9} # 从右数第13个字符(b)开始,取9个字符 → "biancheng" echo ${url:0-13} # 从右数第13个字符开始,取到末尾 → "biancheng.net"
(3)从指定字符(子字符串)开始截取
- •
目标:截取某个字符(如
/
或:
)左边或右边的内容。①
#
或##
:截取指定字符右边的内容- •
格式:
${字符串#*chars}
(匹配第一个chars
) /${字符串##*chars}
(匹配最后一个chars
) - •
作用:忽略左边的所有字符,直到遇到
chars
(不包含chars
本身),然后截取右边的部分。 - •
示例:
url="http://c.biancheng.net/index.html" echo ${url#*:} # 删除第一个 `:` 左边的内容 → "//c.biancheng.net/index.html" echo ${url##*/} # 删除最后一个 `/` 左边的内容 → "index.html"(常用:获取文件名) echo ${url#*/} # 删除第一个 `/` 左边的内容 → "c.biancheng.net/index.html"
②
%
或%%
:截取指定字符左边的内容- •
格式:
${字符串%chars*}
(匹配第一个chars
) /${字符串%%chars*}
(匹配最后一个chars
) - •
作用:忽略右边的所有字符,直到遇到
chars
(不包含chars
本身),然后截取左边的部分。 - •
示例:
url="http://c.biancheng.net/index.html" echo ${url%/*} # 删除最后一个 `/` 右边的内容 → "http://c.biancheng.net" echo ${url%%/*} # 删除第一个 `/` 右边的内容 → "http:"(极端情况)
- •
三、格式化输出:printf 命令
Shell中更精准的输出工具(类似C语言的 printf
),支持格式控制和对齐。
1. 基本语法
printf "格式字符串" "参数1" "参数2" ...
- •
格式字符串:包含普通文本和替换符(如
%s
、%d
),用于控制参数的显示格式。
2. 常用替换符
替换符 | 功能 | 示例 |
---|---|---|
| 字符串 |
|
| 十进制整数 |
|
| 浮点数(可指定小数位) |
|
| 十六进制(小写字母) |
|
| 输出百分号 |
|
3. 常用格式控制
- •
宽度与对齐:
%10s
表示10字符宽(默认右对齐),%-10s
表示左对齐。 - •
小数位:
%.2f
表示保留2位小数。
4. 实战示例
# 基础输出(每行一个参数)
printf "%s\n" 1 2 3 4 # 输出:1\n2\n3\n4# 浮点数控制
printf "%.2f\n" 1 2 3 4 # 输出:1.00\n2.00\n3.00\n4.00# 表格对齐(左对齐姓名和性别)
printf "%-10s %-10s %-4s %s \n" 姓名 性别 年龄 体重
printf "%-10s %-10s %-4s %s \n" 小明 男性 20岁 70KG
printf "%-10s %-10s %-4s %s \n" 小红 女性 18岁 50KG
输出效果:
姓名 性别 年龄 体重
小明 男性 20岁 70KG
小红 女性 18岁 50KG
四、bash配置文件:环境变量的“开关”
bash的配置文件决定了终端的环境(如变量、别名等),按生效范围和登录方式分类。
1. 按生效范围分
- •
全局配置(所有用户生效):
- •
/etc/profile
:登录时加载环境变量和启动程序。 - •
/etc/profile.d/*.sh
:存放多个脚本文件(功能同/etc/profile
)。 - •
/etc/bashrc
:为所有用户的交互式shell提供配置(如别名)。
- •
- •
个人配置(仅当前用户生效):
- •
~/.bash_profile
:用户登录时加载(设置环境变量)。 - •
~/.bashrc
:每次打开交互式shell时加载(设置别名、函数)。
- •
2. 按登录方式分
- •
交互式登录(如终端输入密码登录、
su - 用户名
):- •
加载顺序:
/etc/profile
→/etc/profile.d/*.sh
→~/.bash_profile
→~/.bashrc
→/etc/bashrc
。
- •
- •
非交互式登录(如
su 用户名
、图形界面终端、执行脚本):- •
加载顺序:
/etc/profile.d/*.sh
→/etc/bashrc
→~/.bashrc
。
- •
3. 配置文件功能
类别 | 文件 | 作用 |
---|---|---|
Profile类 |
| 定义环境变量(如 |
Bashrc类 |
| 定义命令别名(如 |
4. 让配置生效
修改配置文件后,需执行以下命令立即生效(无需重启终端):
source 配置文件路径 # 例如:source ~/.bashrc
# 或简写为:
. ~/.bashrc
五、Shell脚本编程:if语句
1、if语句基础:让脚本“做选择”
在Shell脚本中,if语句是最基础的条件判断工具,它能让脚本根据不同的条件执行不同的命令(比如判断用户输入是否合法、数值大小关系等)。就像生活中的“如果...就...”逻辑,if语句的结构清晰易懂。
2、if语句的结构
Shell通过 help if
可以查看官方说明(但有点难懂😅),简单来说它的核心结构是:
if [ 条件判断 ]; then # 如果条件成立(返回状态码0)命令1 # 就执行这里的命令命令2
fi # 结束if语句(像括号一样闭合)# 也可以换行写(更清晰,适合新手)
if [ 条件判断 ]
then命令1命令2
fi
扩展结构(支持更多条件分支):
- •
双分支:如果条件成立执行“then”里的命令,不成立则执行“else”里的命令。
- •
多分支:依次判断多个条件(elif),哪个条件先成立就执行对应的命令,都不成立则执行“else”。
3、if语句的三种形式
1. 单分支:只处理“条件成立”的情况
适用场景:当某个条件满足时执行操作,不满足则什么都不做(或默认跳过)。
格式:
if [ 条件判断式 ]; then命令(条件成立时执行)
fi
示例(检查文件是否存在,存在则打印提示):
if [ -f "/tmp/test.txt" ]; thenecho "文件存在!"
fi
2. 双分支:处理“成立”和“不成立”两种情况
适用场景:根据条件结果执行不同的操作(比如“符合条件做A,不符合做B”)。
格式:
if [ 条件判断式 ]
then命令1(条件成立时执行)
else命令2(条件不成立时执行)
fi
示例(判断数字是否大于10):
read -p "请输入一个数字:" NUM
if [ $NUM -gt 10 ]; thenecho "数字大于10!"
elseecho "数字小于等于10!"
fi
3. 多分支:处理多个条件(依次判断,第一个成立的生效)
适用场景:需要根据不同的范围或情况执行不同操作(比如根据成绩评等级、根据BMI判断健康状态)。
格式:
if [ 条件1 ]; then命令1(条件1成立时执行)
elif [ 条件2 ]; then命令2(条件2成立时执行)
elif [ 条件3 ]; then命令3(条件3成立时执行)
...
else命令N(所有条件都不成立时执行)
fi
关键点:Shell会从上到下依次判断条件,一旦某个条件成立(返回状态码0),就执行对应的命令,然后直接结束整个if语句(后面的条件不再判断)。
4、实战示例:根据BMI判断健康状态
场景需求
用户输入身高(米)和体重(千克),脚本计算BMI指数(公式:BMI = 体重 / (身高^2)),并根据以下规则输出提示:
- •
BMI ≤ 18:太瘦,注意健康
- •
18 < BMI < 24:身材很棒!
- •
BMI ≥ 24:太胖,注意节食和运动
完整脚本代码
#!/bin/bash# 提示用户输入身高(单位:米),并校验输入合法性(0-2米之间,最多两位小数)
read -p "请输入身高(m为单位):" HIGH
if [[ ! "$HIGH" =~ ^[0-2].?[0-9]{,2}$ ]]; thenecho "请不要输入错误的身高(应为0-2米,最多两位小数)";exit 1; # 输入非法,退出脚本(状态码1表示错误)
fi# 提示用户输入体重(单位:千克),并校验输入合法性(1-999千克之间)
read -p "请输入体重(Kg为单位):" WEIGHT
if [[ ! "$WEIGHT" =~ ^[0-9]{1,3}$ ]]; thenecho "请不要输入错误的体重(应为1-999千克)";exit 1;
fi# 计算BMI(使用bc工具处理浮点运算)
BMI=`echo "scale=2; $WEIGHT / ($HIGH * $HIGH)" | bc` # scale=2保留两位小数# 根据BMI范围输出健康提示(多分支判断)
if [ $(echo "$BMI <= 18" | bc) -eq 1 ]; then # BMI ≤ 18echo "你太瘦了,请注意身体健康"
elif [ $(echo "$BMI < 24" | bc) -eq 1 ]; then # 18 < BMI < 24echo "身材很棒!"
else # BMI ≥ 24echo "你太胖了,注意节食,加强运动"
fi
关键细节说明
- 1.
输入校验:
- •
身高用正则
^[0-2].?[0-9]{,2}$
确保是0-2米之间(如1.75、0.5、2.0),最多两位小数。 - •
体重用正则
^[0-9]{1,3}$
确保是1-999之间的整数(如50、120、999)。 - •
如果输入非法,用
exit 1
终止脚本并提示错误。
- •
- 2.
BMI计算:
- •
Shell原生不支持浮点运算,所以用
bc
工具计算(echo "表达式" | bc
)。 - •
scale=2
设置计算结果保留两位小数(如18.50)。 - •
比较浮点数时,同样需要用
bc
(例如[ $(echo "$BMI <= 18" | bc) -eq 1 ]
,若结果为1则表示成立)。
- •
- 3.
多分支逻辑:
- •
先判断BMI ≤ 18(最瘦的情况),再判断18 < BMI < 24(正常偏瘦),最后其他情况归为“太胖”。
- •
一旦某个条件成立(如BMI=15触发第一个条件),后续条件不再判断,直接执行对应命令并结束if语句。
- •
5、注意事项总结
- 1.
条件判断的格式:
- •
[ 条件 ]
中括号两侧必须有空格(如[ $NUM -gt 10 ]
,写成[$NUM -gt 10]
会报错)。 - •
字符串比较用
=
或==
(如[ "$NAME" = "admin" ]
),数值比较用-eq
(等于)、-gt
(大于)、-lt
(小于)等。
- •
- 2.
浮点数处理:
- •
Shell原生只支持整数运算,浮点数必须用
bc
工具(例如计算BMI、比较小数大小)。
- •
- 3.
命令的退出状态码:
- •
if判断的是“命令的退出状态码”(不是条件本身的真假):状态码为0表示“成功/成立”,非0表示“失败/不成立”。
- •
例如
[ $NUM -eq 10 ]
的实质是执行测试命令,返回0则条件成立。
- •
- 4.
代码可读性:
- •
多分支时建议按“从特殊到一般”的顺序写条件(比如先判断极端情况,再判断常见情况)。
- •
复杂的校验逻辑(如输入格式)建议放在最前面,避免后续无效计算。
- •