当前位置: 首页 > news >正文

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. 常用替换符

替换符

功能

示例

%s

字符串

printf "%s" "hello"→ hello

%d

十进制整数

printf "%d" 100→ 100

%f

浮点数(可指定小数位)

printf "%.2f" 3.1415→ 3.14

%x

十六进制(小写字母)

printf "%x" 255→ ff

%%

输出百分号 %本身

printf "%%"→ %

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类

/etc/profile, ~/.bash_profile

定义环境变量(如 PATH)、运行启动脚本

Bashrc类

/etc/bashrc, ~/.bashrc

定义命令别名(如 alias ll='ls -l')、本地变量

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. 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. 2.

    BMI计算​:

    • Shell原生不支持浮点运算,所以用 bc工具计算(echo "表达式" | bc)。

    • scale=2设置计算结果保留两位小数(如18.50)。

    • 比较浮点数时,同样需要用 bc(例如 [ $(echo "$BMI <= 18" | bc) -eq 1 ],若结果为1则表示成立)。

  3. 3.

    多分支逻辑​:

    • 先判断BMI ≤ 18(最瘦的情况),再判断18 < BMI < 24(正常偏瘦),最后其他情况归为“太胖”。

    • 一旦某个条件成立(如BMI=15触发第一个条件),后续条件不再判断,直接执行对应命令并结束if语句。


5、注意事项总结

  1. 1.

    条件判断的格式​:

    • [ 条件 ]中括号两侧必须有空格(如 [ $NUM -gt 10 ],写成 [$NUM -gt 10]会报错)。

    • 字符串比较用 ===(如 [ "$NAME" = "admin" ]),数值比较用 -eq(等于)、-gt(大于)、-lt(小于)等。

  2. 2.

    浮点数处理​:

    • Shell原生只支持整数运算,浮点数必须用 bc工具(例如计算BMI、比较小数大小)。

  3. 3.

    命令的退出状态码​:

    • if判断的是“命令的退出状态码”(不是条件本身的真假):状态码为0表示“成功/成立”,非0表示“失败/不成立”。

    • 例如 [ $NUM -eq 10 ]的实质是执行测试命令,返回0则条件成立。

  4. 4.

    代码可读性​:

    • 多分支时建议按“从特殊到一般”的顺序写条件(比如先判断极端情况,再判断常见情况)。

    • 复杂的校验逻辑(如输入格式)建议放在最前面,避免后续无效计算。

http://www.dtcms.com/a/364128.html

相关文章:

  • Docker零基础入门指南
  • 中文分词器之结巴分词
  • 00 - 浏览器的基础认知
  • lesson52:CSS进阶指南:雪碧图与边框技术的创新应用
  • LLM 能不能发展为 AGI?
  • Shell 秘典(卷七)—— 流刃裁文秘术・sed 玄章精解
  • windows下wsl2 ubuntu开发配置
  • VMWare虚拟网络编辑器:“将主机虚拟适配器连接到此网络”含义
  • RHEL9源码编译MySQL8.0.40
  • 25.9.2_NSSCTF-[HNCTF 2022 WEEK2]TTTTTTTTTea_WP
  • Corrosion: 2靶场渗透
  • 数字化转型的终极关怀:以人为本
  • day3
  • 运作管理学习笔记4-产能规划
  • Flowable——配置使用Flowable-UI
  • 日语学习-日语知识点小记-构建基础-JLPT-N3阶段(24):文法+单词第8回1
  • STM32—SPI协议
  • vLLM推理框架:pagedAttention算法+pipeline介绍+源码逐行注释
  • 【技术详解】 OpenZeppelin ERC1155:Solidity 多代币标准实现原理(附完整 Solidity 源码)​
  • 网络通信IP细节
  • 【Vue】前端 vue2项目搭建入门级(二)
  • 嵌入式概述 与 51 单片机
  • 【单片机day01】
  • 第二章:技术基石:写出“活”的代码(1)
  • 什么时候需要使用虚继承,什么是菱形继承
  • HI3519DRFCV500/HI3519DV500海思核心板IPC算力2.5T图像ISP超高清智能视觉应用提供SDK软件开发包
  • 平衡车-ADC采集电池电压
  • 从 Arm Compiler 5 迁移到 Arm Compiler 6
  • HandyControl 解决不全局引入控件部分内容不显示问题
  • 论文学习30:LViT: Language Meets Vision Transformerin Medical Image Segmentation