1. 拼接

  1) 简单的字符串拼接如:PATH=$PATH:$HOME/bin。如果拼接的字符串包含空格或特殊字符,需要使用双引号括起,如:

var=$HOME/bin  # 注释并不是赋值的一部分
var="$HOME/bin # but this is" # bash .1后,可以使用+=拼接(+=也可用于数组相加)
var=abc $ var=abc
$ var+=xyz
$ echo "$var"
abcxyz

注意:+=的性能较直接拼接的效率高,测试如下:

$ var=; time for i in {..}; do var=${var}foo; done;

real    0m1.251s
user 0m1.144s
sys 0m0.104s
$ var=; time for i in {..}; do var+=foo; done; real 0m0.156s
user 0m0.156s
sys 0m0.000s 

2) 重复字符到指定长度

_repeat(){
#@ 功能:重复字符串到指定长度
_REPEAT=
while (( ${#_REPEAT} < $))
do
_REPEAT+=$
done
} $ _repeat %
$ printf "%s\n" "$_REPEAT"
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

 通过拼接在每个循环中拼接多个实例来提高函数速度:

_repeat(){
#@ 功能:重复字符串到指定长度
_REPEAT=$
while (( ${#_REPEAT} < $))
do
_REPEAT=$_REPEAT$_REPEAT$_REPEAT
done
_REPEAT=${_REPEAT:-:$} ## 裁剪指定长度字符串
} repeat(){
_repeat "$@"
printf "%s\n" "$_REPEAT"
} alert(){ #@ 功能: 打印包含边界及鸣响的警告信息
_repeat "${2:-#}" $(( ${#} + ))
printf '\a%s\n' "$_REPEAT" ## \a = BEL
printf '%2.2s %s %2.2s\n' "$_REPEAT" "$1" "$_REPEAT"
printf '%s\n' "$_REPEAT" } $ alert "Do you really want to detele all your files?" #################################################################################
## Do you really want to detele all your files? ##
#################################################################################

2. 字符处理

没有直接的参数扩展来提供字符串的首字符或尾字符,可借助通配符问号?,以及字符串截取来抽取首字符或尾字符。

$ var=strip
$ allbutfirst=${var#?} # 去除首字符
$ allbutlast=${var%?} # 去除尾字符
$ printf "%8s %8s\n" "$allbutfirst" "$allbutlast"
trip stri
$ first=${var%"$allbutfirst"}
$ last=${var#"$allbutlast"}
$ printf "%8s %8s\n" "$first" "$last"
s p ## 小测试
$ while [ -n "$var" ]; do temp=${var#?}; char=${var%"$temp"}; printf "%s\n" "$char"; var=$temp; done ## 将字符串的每个字母按行打印
s
t
r
i
p
$ while [ -n "$var" ]; do temp=${var%?}; char=${var#"$temp"}; printf "%s\n" "$char"; var=$temp; done ## 将字符串的每个字母反向打印
p
i
r
t
 也可以通过"%c"获取字符串首字符
$ printf -v first "%c" "$var"  # 将原本输出到标注输出的信息赋值给first
$ echo $first
s

3. 大小写转换

Bourne shell中,字符转换可以通过tr命令完成,tr作用:将第一个参数中的字符转换成对应的第二个参数中的字符

$ echo abcdefgh | tr ceh CEH  ## c=>C,e=>E,h=>H
abCdEfgH
$ echo abcdefgh | tr ceh HEC ## c=>H,e=>E,h->C
abHdEfgC
$ echo touchdown | tr 'a-z' 'A-Z' ## 将小写转换为大写
TOUCHDOWN 

POSIX shell中,可以通过参数扩展来完成。

to_upper(){
case $ in
a*) _UPR=A;; b*) _UPR=B;; c*) _UPR=C;; d*) _UPR=D;;
e*) _UPR=E;; f*) _UPR=F;; g*) _UPR=G;; h*) _UPR=H;;
i*) _UPR=I;; j*) _UPR=J;; k*) _UPR=K;; l*) _UPR=L;;
m*) _UPR=M;; n*) _UPR=N;; o*) _UPR=O;; p*) _UPR=P;;
q*) _UPR=Q;; r*) _UPR=R;; s*) _UPR=S;; t*) _UPR=T;;
u*) _UPR=U;; v*) _UPR=V;; w*) _UPR=W;; x*) _UPR=X;;
y*) _UPR=Y;; z*) _UPR=X;; *) _UPR=${%${#?}};;
esac
} $word=function
$to_upper "$word"
$printf "%c%s\n" "$_UPR" "${word#?}"
Function ## 将所有字符转换为大写
_upword(){
local word=$
while [ -n "$word" ] ## 循环直到$word为空
do
to_upper "$word"
_UPWORD=$_UPWORD$_UPR
word=${word#?} ## 移除$word中的首字母
done
} upword(){
_upword "$@"
printf "%s\n" "$_UPWORD"
}

4. 比较内容且不需考虑大小写

当输入为单个字母,例如请求Y或N,可以使用逻辑运算符或(|)或者方括号([])对大小写进行选择。

read ok
case $ok in
y|Y) echo "Great!" ;;
n|N) echo Good-bye; exit ;;
*) echo Invalid entry ;;
esac read ok
case $ok in
[yY]) echo "Great!" ;;
[nN]) echo Good-bye; exit ;;
*) echo Invalid entry ;;
esac 

当输入较长时,以上方法需要将所有的可能组合进行展示,这样的方法较为繁琐。

## 针对于"|",需要列出所有组合
jan | jaN | jAn | jAN | Jan | JAn | JAN) echo "Great!" ;; ## 对于"[]",脚本不宜阅读
read monthname
case $monthname in
[Jj][Aa][Nn]*) month= ;;
[Ff][Ee][Bb]*) month= ;;
## 输入剩余的月份
[Dd][Ee][Cc]*) month= ;;
[-][-] month=$monthname ;; 考虑输入数字的情况
*) echo "Invalid month: $monthname" >& ;;
esac 
较好的方法是将输入统一转换为大写或小写再进行比较:
_upword "$monthname"
case _UPWORD in
JAN*) month= ;;
FEB*) month= ;;
## 输入剩余的月份
DEC*) month= ;;
[-]|[-]) month=$monthname
*) echo "Invalid month: $monthname" >& ;;
esac
bash 4.*中字符转换为大写,也可采用${monthname^^}执行

5. 检查变量名的有效性

检查变量名是否满足仅包含字母、数字和下划线,且只能以字母和下划线开头。

validname(){
case $ in
[!a-zA-Z_]* | *[!a-zA-Z0-9_]*) return ;;
esac
} for name in name1 2var first.name first_name last-name
do
validname "$name" && echo " valid: $name" || echo "invalid: $name"
done valid: name1
invalid: 2var
invalid: first.name
valid: first_name
invalid: last-name 

6. 字符串插入

_insert_string(){ #@功能: 在字符串的指定位置插入字符串
local insert_string_dflt= ## 默认的插入位置
local string=$ ## 被插入的字符串
local i_string=$ ## 待插入字符串
local i_pos=${:-${insert_string_dflt:-}} ## 插入位置
local left right
left=${string::$(( $i_pos - ))}
right=${string:$(( $i_pos - ))}
_insert_string=$left$i_string$right
} insert_string(){
_insert_string "$@" && printf "%s\n" "$_insert_string"
} $ insert_string poplar u
popular
$ insert_string show ad
shadow
$ insert_string tail ops ## 使用默认位置
topsail

7. 覆盖

在一个字符串上覆盖另一个字符串。

_overlay(){
local string=$
local sub=$
local start=$
local left right
left=${string::start-}
right=${string:start+${#sub}-}
_OVERLAY=$left$sub$right
} overlay(){
_overlay "$@" && printf "%s\n" "$_OVERLAY"
} $ {
> overlay pony b
> overlay pony u
> overlay pony s
> overlay pony d
> }
bony
puny
posy
pond 

8. 裁剪不想要的字符

字符串首尾的空格可以通过循环和条件判断完成。

var="    John    "
while : ## 无限循环
do
case $var in
' '*) var=${var#?} ;; ## 如果字符串以空格开始,则移除
*' ') var=${var%?} ;; ## 如果字符串以空格结尾,则移除
*) break; ## 当字符串的头部或尾部均无空格,则退出循环
esac
done 

更有效的方法是找到首尾最长待删除的空格,然后从原始字符串中删除。

var="    John    "
printf "%s|%s\n" "$var" "${#var}"
rightspaces=${var##*[! ]} ## 删除一切直到最后一个非空值
printf "%s|%s\n" "$rightspaces" ${#rightspaces} ## rightspaces为4个空格
var=${var%"$rightspaces"} ## var目前为"John "
printf "%s|%s\n" "$var" "${#var}"
leftspaces=${var%%[! ]*} ## 从第一个非空值删除直到结尾
printf "%s|%s\n" ${leftspaces} ${#leftspaces}
var=${var#"$leftspaces"}
printf "%s|%s\n" "$var" "${#var}" 

进一步封装的方法如下:如果存在第二个参数,则从字符串中删除该参数对应的字符,如果为空,则默认删除空格。

_trim(){ #@ 从$1中删除空格(或$2中的字符)
local trim_string
_TRIM=$
printf "%s|%s\n" "$_TRIM" ${#_TRIM}
trim_string=${_TRIM##*[!${:- }]}
printf "%s|%s\n" "$trim_string" ${#trim_string}
_TRIM=${_TRIM%"$trim_string"}
printf "%s|%s\n" "$_TRIM" ${#_TRIM}
trim_string=${_TRIM%%[!${:- }]*}
printf "%s|%s\n" "$trim_string" ${#trim_string}
_TRIM=${_TRIM#"$trim_string"}
printf "%s|%s\n" "$_TRIM" ${#_TRIM}
} trim(){
_trim "$@" && printf "%s\n" "$_TRIM"
} $ trim " S p a c e d o u t "
S p a c e d o u t
$ trim "0002367.45000"
2367.45 

9. 索引

定位一个字符串在另一个字符串中的索引位置。

_index(){ #@ $2在$1中的位置保存在$_INDEX
local idx
case $ in
"") _INDEX=; return ;;
*"$2"*) idx=${%%"$2"*} ## 提取匹配位置的起始
_INDEX=$(( ${#idx} + )) ;;
*) _INDEX=; return ;;
esac
} index(){
_index "$@" && printf "%d\n" "$_INDEX"
}

例:基于月份的前3个字母,打印出对应的数值

_month2num(){
local month=JAN.FEB.MAR.APR.MAY.JUN.JUL.AUG.SEP.OCT.NOV.DEC
_upword "${1:0:3}" ## 提取$1中的前3个字母,并转换为大写
_index "$month" "$_UPWORD" || return
_MONTH2NUM=$(( $_INDEX / + ))
} month2num(){
_month2num "$@" && printf "%s\n" "$_MONTH2NUM"
}

Bash编程(6) String操作的更多相关文章

  1. bash编程基础

    bash变量 变量命名: 1.不能使用程序中的关键字(保留字) 2.只能使用数字.字母和下划线,且不能以数字开头 3.要见名知义 变量类型: 数值型:精确数值(整数),近似数值(浮点型) 字符型:ch ...

  2. 怎样用 Bash 编程:逻辑操作符和 shell 扩展

    学习逻辑操作符和 shell 扩展,本文是三篇 Bash 编程系列的第二篇. Bash 是一种强大的编程语言,完美契合命令行和 shell 脚本.本系列(三篇文章,基于我的 三集 Linux 自学课程 ...

  3. SHell string操作 转

    本文也即<Learning the bash Shell>3rd Edition的第四章Basic Shell Programming之读书笔记之二,但我们将不限于此. String操作 ...

  4. C# winform编程中多线程操作控件方法

    private void Form1_Load(object sender, EventArgs e) { Thread newthread = new Thread(new ThreadStart( ...

  5. Scala学习教程笔记三之函数式编程、集合操作、模式匹配、类型参数、隐式转换、Actor、

    1:Scala和Java的对比: 1.1:Scala中的函数是Java中完全没有的概念.因为Java是完全面向对象的编程语言,没有任何面向过程编程语言的特性,因此Java中的一等公民是类和对象,而且只 ...

  6. bash编程之循环控制:

    bash编程之循环控制: for varName in LIST; do 循环体 done   while CONDITION; do 循环体 done   until CONDITION; do 循 ...

  7. [shell] Bash编程总结

    由于工作需要,之前的几个月写了一些Bash脚本,主要完成自动测试.打包.安装包等.虽然相比C++编程,要简单.傻瓜,但其在类Unix系统中可以大大提高工作的效率.所以在此对脚本编程过程中一些注意事项进 ...

  8. bash编程的信号捕获:

    bash编程的信号捕获: kill -l KILL无法捕捉:   trap 'COMMAND' SIGNAL,    信号捕捉用于:在中途中止时做一些清理操作.   一. trap捕捉到信号之后,可以 ...

  9. shell编程系列25--shell操作数据库实战之备份MySQL数据,并通过FTP将其传输到远端主机

    shell编程系列25--shell操作数据库实战之备份MySQL数据,并通过FTP将其传输到远端主机 备份mysql中的库或者表 mysqldump 常用参数详解: -u 用户名 -p 密码 -h ...

随机推荐

  1. jQuery基础入门

    一.什么是 jQuery Jquery它是javascript的一个轻量级框架,对javascript进行封装,它提供了很多方便的选择器.供你快速定位到需要操作的元素上面去.还提供了很多便捷的方法. ...

  2. Tomcat负载均衡原理详解及配置(Apache2.2.19+Tomcat7.0.12)

    结构图 JAVA项目一般直接用Tomcat作为Web服务器.为了增加tomcat的性能和稳定性,我们一般采用balance和session同步机制. 下图列出了我们常用也是最简单的解决方案. 说明 1 ...

  3. ZT 基于git的版本管理思路

    http://nvie.com/posts/a-successful-git-branching-model/ 分为5种分支: feature:功能分支,开发人员在此种分支下开发新的功能,开发完成后m ...

  4. Linux Qt 5.x 环境搭建

    Step 1 从Qt官网下载 qt-opensource-linux-x64...run 在linux命令行中给予文件可执行权限 $ chmod u+x qt-opensource-linux...r ...

  5. [数学趣味001]RSA算法原理及示例

    可以先看看这个视频: RSA_Encryption_Algorithm 公开密钥 Perwork: 私钥:Sender和Receiver预先约定加密和解密方案,向其他人保密. 这个实现比较难:向其他人 ...

  6. python读写Excel文件(xlrd、xlwr)

    一.首先需要安装第三方库:pip install xlrd 1.打开Excel文件,由于写入时需要copy,所以这里加上保留原格式参数:formatting_info=True excel_file ...

  7. 用Docker自动构建纸壳CMS

    纸壳CMS可以运行在Docker上,接下来看看如何自动构建纸壳CMS的Docker Image.我们希望的是在代码提交到GitHub以后,容器镜像服务可以自动构建Docker Image,构建好以后, ...

  8. Javascript:日期排班功能实现

     背景: 近期,公司的产品经常会遇到日期排班类似的功能: 需求的排班日期长短不一:有些是两周,有些是四周:要求选中的时候有一个active的状态区分,另外要提供钩子获取选中日期的形如:[2018-04 ...

  9. Django-01Django简介

    1 MVC与MTV模型 MVCWeb服务器开发领域里著名的MVC模式,所谓MVC就是把Web应用分为模型(M),控制器(C)和视图(V)三层,他们之间以一种插件式的.松耦合的方式连接在一起,模型负责业 ...

  10. “全栈2019”Java第五十五章:方法的静态绑定与动态绑定

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...