文章目录

  • 获取变量字符串长度
  • 变量的截取
    • 指定位置截取字符串
    • 匹配字符串截取
  • 变量的字符串替换
  • 删除字符串
  • 变量为空时赋默认值
  • 实战:统计文章单词情况
  • 参考

哭着也要更完
Shell编程目前已经写了3篇:
shell教程(1):有没有兴趣玩耍一下shell版俄罗斯方块?
shell教程(2):积木游戏之认识积木–重要的系统命令
shell教程(3)变量(一):a=1?没那么简单
同期也把这个项目放在github上: Shell-10-Lessons
(https://github.com/neptuneyt/Shell-10-Lessons)

但无论是在公众号还是在GitHub阅读量都惨不忍睹,在GitHub甚至是0Watch、0Star、1Fork,小编已经哭晕在厕所。。。

好在唯一的那个Fork居然是小明同学的偶像天津医科大学的小伊老师,截图为证:

虽然不知道小伊老师是不是手抖误点了Fork键,但小编还是万分激动的,有大佬关注,小编就是哭着也要更完。

前面一讲提到了Shell变量存储数据的主要类型是字符串,例如net="www.baidu.com",其实Shell对字符串变量的操作是十分强大的,想象一下你是程序语言设计开发者,对于一个诸如"www.baidu.com"的变量net,你允许对它进行什么操作呢?是不是要能知道这个字符串的长度?是不是要能随意截取字符串?是不是要能随意替换、删除字符串?变量为空时能不能赋值一个默认的字符串数据?等等的操作,在Shell字符串的变量操作中都是可以实现的。

获取变量字符串长度

想要知道"www.baidu.com"的变量net的长度十分简单,通过${#net}即可获取。

[Neptuneyt]$ net="www.baidu.com"
[Neptuneyt]$ echo ${#net}
13

当然,在Shell中获取字符串变量的长度的方法有许多种,但是${#variable}作为一种系统内建的方法是最快的。

[Neptuneyt]$ echo ${#net}
13
[Neptuneyt]$ echo ${net}|wc -L
13
[Neptuneyt]$ expr length ${net}
13
[Neptuneyt]$ echo ${net}|awk '{print length($0)}'
13

获取字符串长度十分有用,文末给出一个统计文章单词词频数和字长频数的小脚本。

变量的截取

字符串的截取有多种方式,常见的包括:

指定位置截取字符串

[Neptuneyt]$ net="www.baidu.com"
[Neptuneyt]$ # 从第4个字符截取到baidu
[Neptuneyt]$ echo ${net:4:5} #从第4个字符.开始截取5个字符
baidu
[Neptuneyt]$ # 截取baidu.com
[Neptuneyt]$ echo ${net:4}   #起始位置后不接截取字符长度则默认截取之后所有的
baidu.com
[Neptuneyt]$ # 用倒数截取com
[Neptuneyt]$ echo ${net:0-3} #从倒数第三个字符截取到末尾
com
[Neptuneyt]$ echo ${net: -3} #另外的写法,一定要注意冒号和-3之间有空格
com
[Neptuneyt]$ echo ${net:-3}  #不加空格,截取失败
www.baidu.com

匹配字符串截取

[Neptuneyt]$ echo $net
www.baidu.com# 删除匹配字符串的左边,留下剩余部分
[Neptuneyt]$ echo ${net#*.} #这里用*.表示匹配到www.,用一个#表示删除匹配到的字符串,留下剩余的部分
baidu.com# 用2个#号表示尽可能多的删除匹配到的字符串
[Neptuneyt]$ echo ${net##*.}
com# 同理也可以匹配字符串的右边,留下剩余部分
[Neptuneyt]$ echo ${net%.*} #用.*匹配到.com,用%删除
www.baidu# 用2个%号表示尽可能多的删除匹配到的字符串
[Neptuneyt]$ echo ${net%%.*}    #因为2个%,这里.*表示匹配到最长的.baidu.com
www

总的来说:
#*chr表示删除从左到右第一个遇到的字符chr及其左侧的字符
##*chr表示删除从左到右最后一个遇到的字符chr及其左侧的字符(贪婪模式)
%chr*表示删除从右向左第一个遇到的字符chr及其右侧的字符
%%chr*表示删除从右到左最后一个遇到的字符chr及其右侧的字符(贪婪模式)
在键盘上,#在$符的左边,%号在$符的右边,为了便于记忆,大家因此可以记住#删除左边字符,%删除右边字符

变量的字符串替换

想要将netbaidu替换成google怎么写呢?只需${net/baidu/google}即可,需要注意的是原变量并未修改

[Neptuneyt]$ echo ${net/baidu/google} #/匹配字符/替换字符
www.google.com
[Neptuneyt]$ echo $net  #原变量并未修改
www.baidu.com

如果是替换所有匹配到的字符,应该通过${variable//pattern/sub}
例如将net.替换为-/

[Neptuneyt]$ echo ${net//./-}
www-baidu-com
[Neptuneyt]$ echo ${net//.//}
www/baidu/com

除此之外,还有两种专门针对字符串开头和结尾的替换方式
只替换开头匹配的字符串${variable/#pattern/sub}
只替换结尾匹配的字符串${variable/%pattern/sub}
例如对于add=www.xiaomi.com.www的开头或者结尾的www替换为-

[Neptuneyt]$ add=www.xiaomi.com.www
[Neptuneyt]$ echo ${add/#www/-}
-.xiaomi.com.www
[Neptuneyt]$ echo ${add/%www/-}
www.xiaomi.com.-

删除字符串

其实学会了替换字符串删除字符串就更简单了,只需将替换部分写成空即可,即${variable/pattern/null},例如将net的第一个.删除,只需

[Neptuneyt]$ echo ${net/./}
wwwbaidu.com
[Neptuneyt]$ echo ${net/.}  #最后一个/可以不用写
wwwbaidu.com

若要删除所有匹配到的只需即${variable//pattern},例如将net.都删除,只需

[Neptuneyt]$ echo ${net//.}
wwwbaiducom

同理,只删除开头或者结尾匹配到的字符也是类似操作,这里就不赘述了。

变量为空时赋默认值

当我们在写脚本时往往需要给脚本传递一些参数,在Shell中传递参数十分简单,只需利用特殊的位置参数变量诸如$1,$2,$3...${10}...即可,例如,以下脚本传递2个参数:

# PassArgument.sh
#!/bin/env bash
# pass 2 arguments
arg1=$1
arg2=$2
echo $arg1 $arg2[Neptuneyt]$ bash PassArgument.sh Hello word #参数以空格隔开
Hello word

有时候,我们想省掉最后一个参数,让它使用默认值,这个时候只需通过${variable:='default value'}即可,即当变量有值的时候则使用原值,若没有值则使用括号中默认定义好的值。例如,如下脚本表示当第二个参数为空时默认使用定义好的值“word”,否则是用户自己传递的参数:

# PassArgument.sh
#!/bin/env bash
arg1=$1
arg2=$2
echo $arg1 ${arg2:='word'}  #第二个参数设置默认值[Neptuneyt]$ bash PassArgument.sh Hello #第二个参数为空时使用默认值
Hello word
[Neptuneyt]$ bash PassArgument.sh Hello Shell   #第二个参数不为空时使用参数传递的值
Hello Shell

除了${variable:='default value'}外,还有${variable:-'default value'},${variable:+'default value'}${variable:?'default value'},它们有什么区别呢?
对于${variable:='default value'},表示变量为空时把默认值赋值给该变量,例如:

[Neptuneyt]$ net=
[Neptuneyt]$ echo ${net:='www.baidu.com'}
www.baidu.com
[Neptuneyt]$ echo $net
www.baidu.com

对于${variable:-'default value'},表示变量为空时返回默认值但是并不把默认值赋值给该变量, 例如:

[Neptuneyt]$ net=
[Neptuneyt]$ echo ${net:-'www.baidu.com'}
www.baidu.com
[Neptuneyt]$ echo $net  #此时,变量依旧为空

对于${variable:+'default value'},则表示变量不为空时,返回默认值,并且也不重新赋值,例如:

[Neptuneyt]$ net=www.baidu.com
[Neptuneyt]$ echo ${net:+'www.google.com'}
www.google.com
[Neptuneyt]$ echo $net  #不改变变量原值
www.baidu.com

最后,对于${variable:?'default value'},则表示当变量为空时,使用bash风格的报错,例如:

[Neptuneyt]$ net=
[Neptuneyt]$ echo ${net:?'error:null value'}
-bash: net: error:null value

实战:统计文章单词情况

这里想要统计Martin Luther King在1963年著名的I have a dream (戳这里下载)演讲中都使用了哪些词,哪些是高频词,单词字长如何。

思路:
高频词统计:将所有单词单行输出,删除空行,删除,./?等非字母符号,用sort排序后使用uniq统计即可。
字长频数统计:将所有单词单行输出,删除空行,删除,./?等非字母符号,使用while循环遍历每个单词,使用${#variable}统计单词长读频数。

# 高频词统计
echo "高频词统计:"
echo "频数" "单词"
tr " " "\n" <IHaveADream.txt | \
#使用tr将空格转换成换行符,使得每行一个单词,\续行符表示一行命令未写完可换行书写,切记其后什么字符也不能接,包括空格和注释
sed -e "/[^a-Z]/d;/^$/d" | \
#使用sed匹配非字母字符和空行并删除:-e 表示执行多个操作; /[^a-Z]/,双斜线//表示匹配部分,^表示匹配除开后面a-Z的所有字符,d表示对前面匹配部分删除;/^$/表示匹配空行,^、$分别表示行首和行尾
sort |uniq -c |    \
#排序之后使用uniq统计,-c表示统计单词出现的次数
sort -nr | column -t|head #将次数最多的单词排在前面,-n表示按数值排序,-r从大到小倒序排,column -t表格式输出# 字长频数统计
echo
echo "字长频数统计:"
echo "频数" "单词长度"
tr " " "\n" <IHaveADream.txt | \
sed -e "/[^a-Z]/d;/^$/d" | \
while read word
doecho ${#word}
done |\
# 用while和read每次读入一个单词,使用${#word}统计单词长度
sort |uniq -c|sort -nr|column -t|head


不出所料,文中出现次数最多的是冠词和连词类,使用次数最多单词的长度为2、3、4个字母。

如上,短短几句简单的命令行就能完成较为复杂的任务,Shell是不是很简单、便捷呢。希望枯燥的语法也不能阻碍大家学习Shell的脚步,给小编Github的项目多几个Watch、Star、Fork,小编才有继续更的动力啊。

参考

Shell Scripting Tutorial
朱双印博客

shell教程(4)变量(二):字符串变量截取、替换和删除相关推荐

  1. linux读取环境变量替换,linux Shell脚本学习笔记二(变量和环境变量)

    2.变量和环境变量 使用env命令在终端中查看所有与此终端进程相关的环境变量.对于每个进程,在起运行时的环境变量可以使用下面的命令来查看: cat /proc/$PID/environ 其中,将PID ...

  2. linux shell学习笔记(二) 变量和运算符

    1.什么是shell变量?本地变量.环境变量.变量替换(显示变量).位置变量.标准变量.特殊变量.影响变量的命令 2.本地变量:本地变量在用户现在的shell生命期的脚本中使用 variable-na ...

  3. Shell脚本学习之二:变量与运算符

    variable-name = value [root@Gwan ~]# LOCALTEST="test" [root@Gwan ~]# echo ${LOCALTEST} tes ...

  4. php 变量一个字符串 变量,php 输出带变量字符串

    (一) $a=50; echo "Hello World 我有"."$a"."元"; ?> 看此例子,变量a的输出,在php中和Jav ...

  5. php字符串变量,PHP 字符串变量

    PHP 字符串变量 字符串变量用于存储并处理文本. PHP 中的字符串变量 字符串变量用于包含有字符的值. 在创建字符串之后,我们就可以对它进行操作了.您可以直接在函数中使用字符串,或者把它存储在变量 ...

  6. ajax php 返回数组并父子给变量,将字符串变量从PHP发送回数组变量的ajax ...?

    我想将一条消息保存在PHP变量中,并用已返回的其他数组变量发回.例如,我在PHP代码中发生了一些错误检查,并想要一个字符串变量,并将特定的消息发送回我的javascript中使用.将字符串变量从PHP ...

  7. python字符串的删除操作_Python 字符串操作(string替换、删除、截取、复制、连接、比较、...

    去空格及特殊符号 s.strip().lstrip().rstrip(',') Python strip() 方法用于移除字符串头尾指定的字符(默认为空格). 复制字符串 #strcpy(sStr1, ...

  8. matlab最基础教程(四):常用的系统自带函数,符号变量与字符串篇

    matlab最基础教程(四):常用的系统自带函数,符号变量与字符串篇 前言:matlab字面意思是矩阵实验室,软件重点是数值变量的运算.所以在符号变量和字符串的运算上,功能并不强大,我用的也不是很多, ...

  9. linux脚本查看变量类型,Shell变量:Shell变量的定义、删除变量、只读变量、变量类型...

    变量是任何一种编程语言都必不可少的组成部分,变量用来存放各种数据.脚本语言在定义变量时通常不需要指明类型,直接赋值就可以,Shell 变量也遵循这个规则. 在 Bash shell 中,每一个变量的值 ...

  10. 基于python的scip库使用,从基础模型到复杂模型,从一维变量到三维变量

    基础知识 创建模型:model=Model(name)#name是模型名字 创建变量:model.addVar(vtype,name,lb=0,ub=1)#vtype是变量类型,有I(Integer) ...

最新文章

  1. 身份识别协议枚举工具ident-user-enum
  2. SQLite.NET提供程序的选择
  3. 如何利用阿里云安全产品加强你的网站防护能力
  4. MapReduce流程(WordCount案例实现)
  5. Xshell连接Centos完整版(动态ip)
  6. 28个不得不看的经典编程算法!!
  7. asp.net EF+MVC2实战2
  8. 常用C/C++预处理指令详解
  9. Singleton模式的.NET实现
  10. SCADA之父:物理隔离没什么用
  11. C语言自学之路九(用C语言编写小游戏-扫雷)
  12. 驱动数字签名 WIN7 WIN10 32位/64位
  13. 弱分类器 强分类器(弱学习器 强学习器)
  14. 计算机excel表格公式教程,职称计算机Excel教程:显示公式的方法
  15. 飞天系统和linux,用Linux或Windows系统运行抢茅台脚本在性能上有区别吗?
  16. 查看yum安装软件的目录
  17. 2022第十一届PMO大会(线上会议)成功召开
  18. 9 张手绘图:阐明机器学习模型训练全流程
  19. 谷歌推出新优化器Lion:优化算法的符号发现
  20. 李嘉诚在香港做支付,为何要牵手马云?

热门文章

  1. 转行软件测试两个多月,感觉很迷茫,下一步该如何提高自己?
  2. 【APP 测试】绕过华为手机打开 USB 调试需要先登录华为账号问题
  3. 什么是SRE?一文详解SRE运维体系
  4. 让MAC在TouchBar显示网速
  5. itest听力答案2020_大学英语itest2018答案
  6. php以大写字母分割,js按大写字母拆分字符串
  7. linux 运行有道词典,Ubuntu中使用有道词典
  8. Matlab一元线性拟合及F检验
  9. MySql 磁盘满了的处理
  10. [CTFHub] Web RCE Write ups