Bash编程(6) String操作

时间:2022-12-23 14:13:15

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&num; 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. &lbrack;shell&rsqb; 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. C&num; 创建Windows服务

    创建windows服务项目   2 右键点击Service1.cs,查看代码, 用于编写操作逻辑代码 3 代码中OnStart用于执行服务事件,一般采用线程方式执行方法,便于隔一段事件执行一回 END ...

  2. Nginx&plus;Keepalived主从双机热备&plus;自动切换

    1 安装配置nginx 参考: http://www.cnblogs.com/jager/p/4388202.html 2 安装配置keepalived tar xvf keepalived-1.2. ...

  3. Repeater控件中的三目运算

    <asp:Repeater ID="rptimg" runat="server">        <ItemTemplate>      ...

  4. ssh中使用set的地方及ref

    22:30 2014/5/2 1.层与层间的set:  xml方式:在action中曾有service的set方法,service层要有dao的service的set方法,dao曾要有hibernat ...

  5. C&plus;&plus;实现Log&lpar;&rpar;日志函数

    转载请注明原创:http://www.cnblogs.com/StartoverX/p/4600649.html 需求:Log()函数,能够自动根据时间记录日志信息,要求不定参数类型和参数个数. 第一 ...

  6. 关于GROUP BY的应用

    前面收藏了别人的SQL语句操作,可是没有实战,也未知学的如何 正好今天有个事需要做一下 (sql server 2000) 三个表:stuInf,sType,sinInf分别为学生信息表,类型表,信息 ...

  7. Flex——弹性布局

    今天在做项目时,要一个500*100的页面区域做三个橱窗,尼玛可是恶心死我了!光是计算左右内外边距,左右宽度,就废了一上午时间~~好吧,我承认我的数学老师挂得早! 正在苦逼的列公式,定位图片,浮动文字 ...

  8. s2-048远程代码执行漏洞

    在Struts 2.3.x 系列的 Showcase 应用中演示Struts2整合Struts 1 的插件中存在一处任意代码执行漏洞.当你的应用使用了Struts2 Struts1的插件时,可能导致不 ...

  9. HTML学习笔记05-文本格式化

    HTML格式化标签 HTML使用标签<b>与<i>对输出的文本进行格式,如:粗体or斜体 这些HTML标签称为格式化标签 <!DOCTYPE HTML> <h ...

  10. react组件里阻事件冒泡

    e.nativeEvent.stopImmediatePropagation();