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. Spring学习(二)——使用Gradle构建一个简单的Spring MVC Web应用程序

    1.新建一个Gradle工程(Project) 在新建工程窗口的左侧中选择 [Gradle],右侧保持默认选择,点击next,模块命名为VelocityDemo. 2.在该工程下新建一个 module ...

  2. redis安装 卸载 启动 关闭

    一 redis安装 第一步:在VMware中安装CentOS(参考Linux教程中的安装虚拟机) 第二步:在Linux下安装gcc环境 [root@hadoop ~]#yum install gcc- ...

  3. Heimich manoeuvre 海姆利克氏操作

    食物,异物卡喉的问题屡见不鲜,造成呼吸困难,甚至心跳停止. 一旦发生这个状况,千万千万不要叩击病人的背部,应在迅速联系医院救援的同时,对病人进行现场急救. heimlich的实施最重要的功能是可以实现 ...

  4. Javascript中的闭包(转载)

    前面的话: 闭包,是 javascript 中重要的一个概念,对于初学者来讲,闭包是一个特别抽象的概念,特别是ECMA规范给的定义,如果没有实战经验,你很难从定义去理解它.下面是作者从作用域链慢慢讲到 ...

  5. 当页面滚动到距顶部一定高度时某DIV自动隐藏和显示

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. redis在Linux上的部署和jedis简单使用

    一.redis的安装 这里演示的版本是Redis4.0.6,Linux系统是CentOS6.7,Jdk1.7,Jedis2.8.1 这是官方文档介绍的安装方式 下载,解压,编译: $ wget htt ...

  7. Codeforces Round #556 (Div. 2) - C. Prefix Sum Primes(思维)

    Problem  Codeforces Round #556 (Div. 2) - D. Three Religions Time Limit: 1000 mSec Problem Descripti ...

  8. px,em, rem的区别,在项目中怎么使用rem.

    一.px px像素,绝对单位.像素px是相对于显示器屏幕分辨率而言的,是一个虚拟的长度单位,是计算机系统的数字化图像长度单位,如果px要换算成物理长度单位,需要指定精度DPI. 二.em em是相对长 ...

  9. fastdfs-client-java操作fastdfs

    一.在https://github.com/happyfish100/fastdfs-client-java 下载客户端,解压后并执行ant命令,在E:\tools\libs\fastdfs\fast ...

  10. [SCOI2018]游泳池(计算几何+分数规划+最大权闭合子图)

    题目链接 https://www.luogu.org/problemnew/show/U56187 注:题面参考了网上的其他博客,并非原题题面,因此数据范围可能有误.数据为原创数据. 题解 其实就是许 ...