Shell编程中的字符串操作与变量处理
在编程的世界里,字符串和变量的处理是任何语言中都非常重要的一部分。在Shell编程中,这一点尤为明显。本文将深入探讨Shell中如何使用${}
和()
进行高级字符串操作和变量处理。这些操作不仅能让你的代码更简洁,也能让你更加灵活地处理各种编程场景。
“代码是写给人看的,顺便能在机器上运行。” —— Donald Knuth
为什么需要高级字符串操作和变量处理?
在编程中,我们经常需要对字符串进行各种各样的操作,比如提取子字符串、替换字符、改变大小写等。同时,变量的动态处理也是编程中不可或缺的一部分。掌握这些高级操作,就像是给自己的工具箱里添加了一把瑞士军刀,无论是数据处理还是系统操作,都能让你游刃有余。
在这里,我将介绍一些常用但可能不太为人知的Shell字符串操作和变量处理技巧。这些技巧在实际编程中有着广泛的应用,掌握它们将大大提升你的编程效率。
“The most effective debugging tool is still careful thought, coupled with judiciously placed print statements.” —— Brian W. Kernighan, co-author of “The C Programming Language”
现在,让我们开始这一段令人兴奋的学习之旅吧!
注意:本文中的代码示例主要使用Bash Shell环境。如果你使用的是其他Shell环境,大部分示例仍然适用,但某些细微的语法可能会有所不同。
接下来,请跟随我一起深入了解这些高级操作吧!
“Simplicity is prerequisite for reliability.” —— Edsger W. Dijkstra
shell中${}和()的含义
在 Shell 脚本中,$()
和 ${}
有不同的用途:
$()
$()
用于命令替换。它会执行括号内的命令,并将输出替换为该命令的标准输出。例如:
today=$(date) echo "Today's date is $today"
这里,$(date)
会执行 date
命令,并将其输出保存在变量 today
中。
这与使用反引号 `
(不是单引号)达到相同目的的旧语法相似,但更为现代,并允许嵌套。
${}
${}
主要用于变量替换和字符串操作。例如:
name="Alice" echo "Hello, ${name}"
这里,${name}
会被替换为变量 name
的值,即 “Alice”。
更复杂的用法包括字符串切片、获取字符串长度、查找和替换等:
# 获取字符串长度 length=${#name} # 截取子字符串 partial=${name:0:3} # 查找和替换 new_name=${name/Alice/Bob}
${}
在以下情况下特别有用:
- 当变量名与周围的文本混淆时。例如,
${name}_file
与${name}_file
不同。 - 执行更复杂的字符串操作,如上面的例子。
简而言之,$()
用于命令替换,而 ${}
用于变量替换和字符串操作。两者都是 Shell 脚本中常用的特性。
shell中${}和()的使用实例
截断功能
“${1^^}_DOC_CHANGE_PID” #变量转换为大写
“${1,}_DOC_CHANGE_PID” #变量转换为小写
${!DOC_CHANGE_PID} #取变量的值
"${1^^}_DOC_CHANGE_PID" #变量转换为大写 "${1,,}_DOC_CHANGE_PID" #变量转换为小写 ${!DOC_CHANGE_PID} #取变量的值
- ${file#*/}: 拿掉第一条/及其左边的字符串:dir1/dir2/dir3/my.file.txt
- ${file##*/}: 拿掉最后一条/及其左边的字符串:my.file.txt
- ${file#*.}: 拿掉第一个.及其左边的字符串:file.txt
- ${file##*.}: 拿掉最后一个.及其左边的字符串:txt
- ${file%/*}: 拿掉最后条/及其右边的字符串:/dir1/dir2/dir3
- ${file%%/*}: 拿掉第一条/及其右边的字符串:(空值)
- ${file%.*}: 拿掉最后一个.及其右边的字符串:/dir1/dir2/dir3/my.file
- ${file%%.*}: 拿掉第一个.及其右边的字符串:/dir1/dir2/dir3/my
字符串提取
单一符号是最小匹配﹔两个符号是最大匹配。
- ${file:0:5}:提取最左边的 5 个字节:/dir1
- ${file:5:5}:提取第 5 个字节右边的连续 5 个字节:/dir2
- 字符串替换
- ${file/dir/path}:将第一个 dir 提换为 path:/path1/dir2/dir3/my.file.txt
- ${file//dir/path}:将全部 dir 提换为 path:/path1/path2/path3/my.file.txt
- 针对不同的变量状态赋值(没设定、空值、非空值)
- ${file-my.file.txt}: 若$file没有设定,则使用my.file.txt作返回值。(空值及非空值时不作处理)
- ${file:-my.file.txt}:若$file没有设定或为空值,则使用my.file.txt作返回值。(非空值时不作处理)
- ${file+my.file.txt}: 若$file设为空值或非空值,均使用my.file.txt作返回值。(没设定时不作处理)
- ${file:+my.file.txt}:若$file为非空值,则使用my.file.txt作返回值。(没设定及空值时不作处理)
- ${file=my.file.txt}: 若$file没设定,则使用my.file.txt作返回值,同时将$file 赋值为 my.file.txt。(空值及非空值时不作处理)
- ${file:=my.file.txt}:若$file没设定或为空值,则使用my.file.txt作返回值,同时将 $file 赋值为 my.file.txt。(非空值时不作处理)
- ${file?my.file.txt}: 若$file没设定,则将my.file.txt输出至 STDERR。(空值及非空值时不作处理)
- ${file:?my.file.txt}:若$file没设定或为空值,则将my.file.txt输出至STDERR。(非空值时不作处理)
注意:
":+"的情况是不包含空值的.
“:-”, ":="等只要有号就是包含空值(null).
变量的长度
${#file}
数组运算
- A=(a b c def)
- ${A[@]} 或 ${A[*]} 可得到 a b c def (全部组数)
- ${A[0]} 可得到 a (第一个组数),${A[1]} 则为第二个组数…
- ${#A[@]} 或 ${#A[*]} 可得到 4 (全部组数数量)
- ${#A[0]} 可得到 1 (即第一个组数(a)的长度),${#A[3]} 可得到 3 (第四个组数(def)的长度)
示例
**
#介绍下Shell中的${}、##和%%使用范例,本文给出了不同情况下得到的结果。 #假设定义了一个变量为: #代码如下: file=/dir1/dir2/dir3/my.file.txt #可以用${ }分别替换得到不同的值: ${file#*/}#删掉第一个 / 及其左边的字符串:dir1/dir2/dir3/my.file.txt ${file##*/}#删掉最后一个 / 及其左边的字符串:my.file.txt ${file#*.}#删掉第一个 . 及其左边的字符串:file.txt ${file##*.}#删掉最后一个 . 及其左边的字符串:txt ${file%/*}#删掉最后一个 / 及其右边的字符串:/dir1/dir2/dir3 ${file%%/*}#删掉第一个 / 及其右边的字符串:(空值) ${file%.*}#删掉最后一个 . 及其右边的字符串:/dir1/dir2/dir3/my.file ${file%%.*}#删掉第一个 . 及其右边的字符串:/dir1/dir2/dir3/my #记忆的方法为: # 是 去掉左边(键盘上#在 $ 的左边) #%是去掉右边(键盘上% 在$ 的右边) #单一符号是最小匹配;两个符号是最大匹配 ${file:0:5}#提取最左边的 5 个字节:/dir1 ${file:5:5}#提取第 5 个字节右边的连续5个字节:/dir2 #也可以对变量值里的字符串作替换: ${file/dir/path}#将第一个dir 替换为path:/path1/dir2/dir3/my.file.txt ${file//dir/path}#将全部dir 替换为 path:/path1/path2/path3/my.file.txt
结语:编程、思考与持续成长
在编程的世界里,每一行代码都是一种表达,每一个问题都是一个挑战。正如我们在本文中探讨的 Bash 脚本,简单的代码背后往往蕴含着丰富的思考和解决问题的智慧。编程不仅是一种技术活动,更是一种思维的锻炼和人类创造力的体现。
正如Bjarne Stroustrup在《The C++ Programming Language》中所说:“编程是理解的艺术。”
从编程的角度看,每一个错误、每一个挑战都是一次成长的机会。这些“错误”实际上是我们与计算机、与问题、甚至与自己内心的一次深度对话。它们不仅仅是困扰,更是一种启示,引导我们去优化思维,去完善解决方案。
我诚挚地邀请大家加入这场关于编程和思考的旅程。无论你是编程的新手,还是经验丰富的开发者,都请不吝赐教,分享你的见解和经验。你的每一次互动,无论是点赞、评论、分享还是关注,都是对我持续创作和分享的最大鼓励和支持。
感谢你花时间阅读这篇文章,如果你觉得有价值,请不要忘记收藏和分享。也欢迎你对博客内容提出宝贵的建议和问题,因为每一个问题都可能是下一篇文章的起点。
让我们一起,在编程的道路上,持续学习,持续成长。
“代码如诗,智慧如光。” —— 未知
感谢阅读,期待与你再次相遇在编程和思考的交汇点。