在日常运维工作中,经常会碰到需要在一个字符串中截取我们需要的某些字符的需求,之前介绍了Shell脚本中数组的使用方法,这里介绍下基于字符串的截取的方法。在shell中截取字符串的方法有下面集中:
${var#*/}
${var##*/}
${var%/*}
${var%%/*}
${var:start:len}
${var:start}
${var:0-start:len}
${var:0-start}

可以总结为:
********************************************
#         删除最小的匹配前缀
##       删除最大的匹配前缀
%        删除最小的匹配后缀
%%     删除最大的匹配后缀
********************************************

1)获得字符串的长度
语法:${#var}

[root@kevin~]# cat test.sh
#!/bin/bash
str="http://www.kevin.com/shibo/anhuigrace"
echo "string: [${str}]" length=${#str}
echo "length: [${length}]" 执行结果为:
[root@kevin~]# sh test.sh
string: [http://www.kevin.com/shibo/anhuigrace]
length: [37]

2)使用 # 和 ## 获取尾部子字符串(*号在分隔符的前面,就去掉其之前的字符)
2.1) # 最小限度从前面截取word
语法:${parameter#*word} , 即截取 "第一个分隔符word及其之前的字符全部删掉"后的字符

[root@kevin~]# cat test.sh
#!/bin/bash
str="http://www.kevin.com/shibo/anhuigrace"
echo "string: [${str}]" #分割符为'/'
substr=${str#*/}
echo "substr: [${substr}]" 执行结果为:
[root@kevin~]# sh test.sh
string: [http://www.kevin.com/shibo/anhuigrace]
substr: [/www.kevin.com/shibo/anhuigrace]

2.2)## 最大限度从前面截取word
语法:${parameter##*word},即截取 "最后一个分隔符word及其之前的字符全部删掉"后的字符

[root@kevin~]# cat test.sh
#!/bin/bash
str="http://www.kevin.com/shibo/anhuigrace"
echo "string: [${str}]" #分割符为'/'
substr=${str##*/}
echo "substr : [${substr}]" 执行结果为:
[root@kevin~]# sh test.sh
string: [http://www.kevin.com/shibo/anhuigrace]
substr : [anhuigrace]

3)使用 % 和 %% 获取头部子字符串 (*在分隔符的后面,就去掉其之后的字符)
3.1)% 最小限度从后面截取word
语法:${parameter%word*},即截取 "最后一个分隔符word及其之后的字符全部删掉"后的字符

[root@kevin~]# cat test.sh
#!/bin/bash
str="http://www.kevin.com/shibo/anhuigrace"
echo "string: [${str}]" substr=${str%/*}
echo "substr : [${substr}]" 执行结果为:
[root@kevin~]# sh test.sh
string: [http://www.kevin.com/shibo/anhuigrace]
substr : [http://www.kevin.com/shibo]

3.2)%% 最大限度从后面截取word
语法:${parameter%%*word},即截取 "第一个分隔符word及其之后的字符全部删掉"后的字符

[root@kevin~]# cat test.sh
#!/bin/bash
str="http://www.kevin.com/shibo/anhuigrace"
echo "string: [${str}]" substr=${str%%/*}
echo "substr : [${substr}]" 执行结果为:
[root@kevin~]# sh test.sh
string: [http://www.kevin.com/shibo/anhuigrace]
substr : [http:]

4)使用 ${var:} 模式获取子字符串
4.1)指定从左边第几个字符开始以及子串中字符的个数
语法:${var:start:len}

[root@kevin~]# cat test.sh
#!/bin/bash
str="http://www.kevin.com/shibo/anhuigrace"
echo "string: [${str}]" #其中的 0 表示左边第一个字符开始,7 表示子字符的总个数。
substr=${str:0:7}
echo "substr : [${substr}]" 执行结果为:
[root@kevin~]# sh test.sh
string: [http://www.kevin.com/shibo/anhuigrace]
substr : [http://]

4.2)从左边第几个字符开始一直到结束
语法:${var:7}

[root@kevin~]# cat test.sh
#!/bin/bash
str="http://www.kevin.com/shibo/anhuigrace"
echo "string: [${str}]" #其中的7表示左边第8个字符开始 (如果是${str:7:5},就表示从左边第8个字符开始截取,截取5个字符)
substr=${str:7}
echo "substr : [${substr}]" 执行结果为:
[root@kevin~]# sh test.sh
string: [http://www.kevin.com/shibo/anhuigrace]
substr : [www.kevin.com/shibo/anhuigrace]

4.3)从右边第几个字符开始以及字符的个数
语法:${var:0-start:len};即${var:0-8,3} 和 ${var:2-10:3} 和 ${var:5:13:3} 是一样的,即从右边第8个开始截取,截取3个字符。 即8-0=10-2=13-5=8

[root@kevin~]# cat test.sh
#!/bin/bash
str="http://www.kevin.com/shibo/anhuigrace"
echo "string: [${str}]" #其中的 0-23 表示右边算起第23个字符开始,5 表示字符的个数
substr=${str:0-23:5}
echo "substr : [${substr}]" 执行结果为:
[root@kevin~]# sh test.sh
string: [http://www.kevin.com/shibo/anhuigrace]
substr : [in.co]

4.4)从右边第几个字符开始一直到结束
语法:${var:0-start}

[root@kevin~]# cat test.sh
#!/bin/bash
str="http://www.kevin.com/shibo/anhuigrace"
echo "string: [${str}]" #其中的 0-6 表示右边算起第6个字符开始
substr=${str:0-6}
echo "substr : [${substr}]" 执行结果为:
[root@kevin~]# sh test.sh
string: [http://www.kevin.com/shibo/anhuigrace]
substr : [igrace]

####################  $( ) ${ }$(( ))的用法区别  ####################

一、$( ) 与 ` ` (反引号)
########################################################################################################################
在Shell 中,$( ) 与 ` ` (反引号) 都是用来做命令替换用的。
命令替换:就是完成()或反引号里的命令行,然后将其结果替换出来,再重组命令行。 例如:
[root@ss-server ~]# echo "this is $(date +%Y-%m-%d)"
this is 2020-01-08
[root@ss-server ~]# echo "this is `date +%Y-%m-%d`"
this is 2020-01-08 ###### 使用 $( ) 的理由 ######
1)` ` 反引号很容易与 ' ' 单引号搞混乱;
2)在多层次的复合替换中,` `反引号须要额外的跳脱( \` )处理,而 $( ) 则比较直观; 比如命令:command1 `command2 `command3` `
原本的意图:
是要在 command2 `command3` 中先将 command3 提换出来给 command 2 处理,然后再将结果传给 command1 `command2 …` 来处理。
然而,真正的结果:
在命令行中却是分成了 `command2 ` 与 ''两段。 小示例:
使用多层次的``反引号
[root@ss-server ~]# echo `echo `date +%Y-%m-%d``
date +%Y-%m-%d 换成 $( ) 就没问题了,做多少层的替换都没问题!
[root@ss-server ~]# echo $(echo $(date +%Y-%m-%d))
2020-01-08 ###### $( ) 的不足 ######
$( ) 并不见的每一种 shell类型都能使用,如果使用 bash2 的话,肯定没问题。 二、${ } 用来作变量替换
########################################################################################################################
一般情况下,$var 与 ${var} 并没有什么不一样。但是用 ${ } 会比较精确的界定变量名称的范围! 如下:
[root@ss-server ~]# a=b
[root@ss-server ~]# echo $ab [root@ss-server ~]# echo ${a}b
bb 原本是打算先将 $a 的结果替换出来,然后再补一个 b 字母于其后,
但在命令行上,真正的结果却是只会提换变量名称为 ab 的值出来,结果没有ab的变量,结果就为空了!
若使用 ${ } 就没问题。 再注意区分下面的情况:即设置变量,以 = 左边的为变量名,如以右边为变量名则无效!
[root@ss-server ~]# a=b
[root@ss-server ~]# echo ${b} [root@ss-server ~]# echo ${a}
b
[root@ss-server ~]# echo $a b
b b
[root@ss-server ~]# echo ${a}${b}
b
[root@ss-server ~]# echo ${a}${a}
bb
[root@ss-server ~]# echo ${b}${b} [root@ss-server ~]# ######################################################################
下面开始介绍下${ } 的一些高阶功能 先定义一个变量,下面示例都是以给变量做说明:
[root@ss-server ~]# file=/dir1/dir2/dir3/my.file.txt 1)可以用 ${ } 分别替换获得不同的值 ---------------------------
使用#和%进行截取字符串的方法在文章上面已经详细介绍了,这里就不做过多说明了。 ${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 关于上面使用 # 和 % 的记忆方法为:
# 是删除掉指定字符串左边的!
% 是删除掉指定字符串右边的! 单一符号是最小匹配﹔两个符号是最大匹配
#*str 是删除掉第一个str及其左边的内容; ##*str 是删除掉最后一个str及其左边的内容;
%str* 是删除掉最后一个str及其右边的内容;%%str* 是删除掉第一个str及其右边的内容! 下面的截图字符串的方法在文章上面已经详细介绍了,这里就不做过多说明了。
${file:0:5}: 表示提取最左边的5个字节,即结果为:/dir1
${file:5:10}: 表示提取第5个字节右边的连续10个字节,即结果为:/dir2/dir3 如下脚本示例:
[root@bzacbsc01ap2001 ~]# hostname
bzacbsc01ap2001 主机名中第3到第6字符是本机的业务模块名称,也就是cbs。下面脚本中的表示从a字符串左边的第4个字符开始截取,截取3个字符(即3:3)
[root@bzacbsc01ap2001 ~]# cat test.sh
#!/bin/bash
a=$(hostname)
b=${a:3:3}
APP=$(echo ${b}) echo "本机tomcat的安装目录为: /opt/${APP}/tomcat" 执行结果为:
[root@bzacbsc01ap2001 ~]# sh test.sh
本机tomcat的安装目录为: /opt/cbs/tomcat 2)可以使用 ${ } 对变量值里的字符串作替换 ---------------------------
${file/dir/path}: 表示将第一个 dir 提换为 path,即结果为:/path1/dir2/dir3/my.file.txt
${file//dir/path}:表示将全部 dir 提换为 path,即结果为:/path1/path2/path3/my.file.txt 如下示例:
[root@ss-server ~]# Test_Name=kevin/bo/AnHui
[root@ss-server ~]# Test_Path=${Test_Name////.} #使用//将变量中所有的/替换为.
[root@ss-server ~]# echo ${Test_Path}
kevin.bo.AnHui
[root@ss-server ~]# Test_Path=${Test_Path/.//} #使用/将变量中第一个.替换为/
[root@ss-server ~]# echo ${Test_Path}
kevin/bo.AnHui
[root@ss-server ~]# Test_Path=$(echo $Test_Path | tr '[A-Z]' '[a-z]')
[root@ss-server ~]# echo ${Test_Path}
kevin/bo.anhui 可以在shell脚本中进行变量的多次替换,如下:
[root@ss-server ~]# vim test.sh
#!/bin/bash
MODULE_NAME=$1
.........
# image信息
IMAGE_PATH=${MODULE_NAME////.}
IMAGE_PATH=${IMAGE_PATH/.//}
IMAGE_PATH="$IMAGE_PATH.$BRANCH.$SERVICE_NAME"
IMAGE_PATH=$(echo $IMAGE_PATH | tr '[A-Z]' '[a-z]')
TAG=${REVISION:0:7}
......... 3)使用 ${ } 还可以针对不同的变量状态赋值 (没设定、空值、非空值) ---------------------------
${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。 (非空值时不作处理) ${1:-NULL} 表示是当$1为空时,自动将NULL替换成$1所要带入的变量值。
${2:-NULL} 表示是当$2为空时,自动将NULL替换成$2所要带入的变量值。 例如:
[root@ss-server ~]# kevin=123
[root@ss-server ~]# echo ${kevin+anhui}
anhui [root@ss-server ~]# echo ${haha:=null} #haha变量没有设定,则使用=后面的null作为传回值
null 也可以在shell脚本中进行变量的状态赋值
[root@ss-server ~]# vim test.sh
#!/bin/bash
.........
AFS_ENV=${AFS_ENV:=null}
AFS_APPID=${AFS_APPID:=null}
AFS_CLUSTER=${AFS_CLUSTER:=null}
AFS_JARNAME=${AFS_JARNAME:=null}
......... 对于上面的理解,在于一定要分清楚 unset 与 null 及 non-null 这三种赋值状态。
一般而言, : 与 null 有关, 若不带 : 的话, null 不受影响, 若带 : 则连 null 也受影响!
[root@ss-server ~]# kevin=123
[root@ss-server ~]# echo ${kevin:+anhui}
anhui
[root@ss-server ~]# kevin=
[root@ss-server ~]# echo ${kevin:+anhui} [root@ss-server ~]# unset kevin
[root@ss-server ~]# echo ${kevin:+anhui} [root@ss-server ~]# 使用${#var}可以计算出变量的长度
[root@ss-server ~]# echo ${file}
/dir1/dir2/dir3/my.file.txt
[root@ss-server ~]# echo ${#file}
27 三、bash的组数(array)处理方法
########################################################################################################################
一般而言,A="be sh se cho" 这样的变量只是将 $A 替换为一个单一的字符串,
但是改为 A=(be sh se cho) ,则是将 $A 定义为组数,所以说数组定义需要使用()括号!! 关于数组的使用,之前已经在 https://www.cnblogs.com/kevingrace/p/5761975.html 这篇文章中详细介绍了,这里简略说下: 组数常用的几个替换方法:
${A[@]} 或 ${A[*]} 表示获得全部组数,即得到be sh se cho 。
${A[0]} 表示获得数组中的第1个组数。同理,${A[1]} 获得的是第2个组数。
${#A[@]} 或 ${#A[*]} 表示获得全部组数数量。
${#A[0]} 表示获得第一个组数的长度,即be的长度,为2; 同理,${#A[3]} 表示获得第四个组数的长度,即cho的长度,为3;
A[1]=haha 表示将第2个组数重新定义为haha; 同理,A[3]=heihei 表示将第4个组数重新定义为heihei; 四、$(( )) 用途:用来作整数运算
########################################################################################################################
在 bash 中,$(( )) 的整数运算符号大致有这些:
+ - * / 分别表示为 "加、减、乘、除"。
% 表示余数运算
& | ^ ! 分别表示分别为 "AND、OR、XOR、NOT" 运算。 例如:
[root@ss-server ~]# a=6;b=7;c=8
[root@ss-server ~]# echo $(( a+b*c ))
62
[root@ss-server ~]# echo $(( (a+b+3)/c ))
2
[root@ss-server ~]# echo $(( (a*b)%c))
2 使用$[]、let、$(()) 都可以作为整数运算,效果是一样的!
[root@ss-server ~]# echo $((4*9))
36
[root@ss-server ~]# echo $[4*9]
36
[root@ss-server ~]# let a=4*9
[root@ss-server ~]# echo $a
36
[root@ss-server ~]# let "a=4*9"
[root@ss-server ~]# echo $a
36
[root@ss-server ~]# let a="3+5"
[root@ss-server ~]# echo $a
8
[root@ss-server ~]# a=18
[root@ss-server ~]# let a++
[root@ss-server ~]# echo $a
19 事实上,单纯用 (( )) 也可重定义变量值。
(( )) 这组符号的作用与 let 指令相似,用在算数运算上,是 bash 的内建功能。所以,在执行效率上会比使用 let指令要好许多。
[root@ss-server ~]# a=10; ((a++))
[root@ss-server ~]# echo ${a}
11 [root@ss-server ~]# cat test.sh
#!/bin/bash
(( a = 10 ))
echo -e "inital value, a = $a\n" (( a++))
echo "after a++, a = $a" [root@ss-server ~]# sh test.sh
inital value, a = 10 after a++, a = 11 更多内容,可参考另一篇文章的总结: https://www.cnblogs.com/kevingrace/p/5896386.html

系统重启后DNS地址默认修改修改引起的一次事故(Tomcat报错:java.net.UnknownHostException)的更多相关文章

  1. CentOS6重启后DNS被还原的解决办法

    CentOS6重启后DNS被还原的解决办法 http://luyx30.blog.51cto.com/1029851/1070765/ centos6.5的64位系统,修改完/etc/sysconfi ...

  2. Debian8.1 安装samba与windows共享文件,在系统重启后samba服务无法自动启动

    Debian8.1安装配置完成并成功与window共享文件后,系统重启后再次访问时出现如下问题 (图)的解决方法 手动重启samba sudo /etc/init.d/samba start 从win ...

  3. ovs2.7 在系统重启后,再次使用时提示数据库无法连接的问题。

    问题现象如下,ovs开始安装后,对ovs的操作是正常的,但是,现在系统重启后,OVS的操作第一条命令就失败,如下: 问题解决方法: 参考  http://blog.csdn.net/xyq54/art ...

  4. 系统重启后,mr程序不生成当前时间段的MRx文件问题

    系统重启后,mr程序不生成当前时间段的MRx文件问题 2019-4-2 之前使用正常的MR程序,系统重启后无法生成MRE\MRO\MRS文件. 服务器有两个时钟:硬件时钟和系统时钟 硬件时钟从根本上讲 ...

  5. windows中修改catalina.sh上传到linux执行报错This file is needed to run this program解决

    windows中修改catalina.sh上传到linux执行报错This file is needed to run this program解决 一.发现问题 由于tomcat内存溢出,在wind ...

  6. 完美解决JavaIO流报错 java.io.FileNotFoundException: F:\ (系统找不到指定的路径。)

    完美解决JavaIO流报错 java.io.FileNotFoundException: F:\ (系统找不到指定的路径.) 错误原因 读出文件的路径需要有被拷贝的文件名,否则无法解析地址 源代码(用 ...

  7. Eclipse启动Tomcat报错,系统缺少本地apr库

    Eclipse启动Tomcat报错,系统缺少本地apr库. Tomcat中service.xml中的设置情况. 默认情况是HTTP协议的值:protocol="HTTP/1.1" ...

  8. 开着idea,死机了,关机重启。重启之后,重新打开idea报错java.lang.AssertionError:upexpected content storage modification

    开着idea,死机了,关机重启.重启之后,重新打开idea报错java.lang.AssertionError:upexpected content storage modification. goo ...

  9. 解决win7系统重启后ip丢失问题,即每次电脑重启都要重新设置ip地址,重启后ip地址没了

    自己制作的Ghost盘上网有点问题,每次重启后电脑的ip地址被还原,要重新设置 百度后终于找解决办法,在此记录. 第一步:点击左下角的WIN图标,输入CMD然后回车,打开DOS模式窗口. 第二步:在D ...

随机推荐

  1. 07-OpenLDAP密码审计

    OpenLDAP密码审计 阅读视图 密码审计的作用 操作实践 1. 密码审计的作用 开启密码审计的功能主要用于记录OpenLDAP用户修改密码,以及密码审计. 2. 操作实践 开启密码审计模块并配置密 ...

  2. 洗礼灵魂,修炼python(54)--爬虫篇—urllib2模块

    urllib2 1.简介 urllib2模块定义的函数和类用来获取URL(主要是HTTP的),他提供一些复杂的接口用于处理: 基本认证,重定向,Cookies等.urllib2和urllib差不多,不 ...

  3. 安装VisualSVN Server 报"Service 'VisualSVN Server' failed to start. Please check VisualSVN Server log in Event Viewer for more details"错误.原因是启动"VisualSVN Server"失败

    安装VisualSVN Server 报"Service 'VisualSVN Server' failed to start. Please check VisualSVN Server ...

  4. 弱符号__attribute__((weak))

    弱符号是什么? 弱符号: 若两个或两个以上全局符号(函数或变量名)名字一样,而其中之一声明为weak symbol(弱符号),则这些全局符号不会引发重定义错误.链接器会忽略弱符号,去使用普通的全局符号 ...

  5. Django电商项目---完成用户中心(订单中心+收货地址)day7

    完成用户中心(收货地址) df_user/views.py df_user/urls.py templates/df_user/user_center_site.html 界面显示 完成用户中心(全部 ...

  6. 软件工程实践_Task1

    (1)回想一下你初入大学时对计算机专业的畅想 当初你是如何做出选择计算机专业的决定的? 说起来,当初选择计算机专业的缘由,更多应该归因于兴趣.虽然对CS全然不知,但也一点都不妨碍对它的神奇感到向往.再 ...

  7. QT插件+ROS 3 导入现有ROS包

    http://blog.csdn.net/u013453604/article/details/52167213#t5

  8. Arduino IDE for ESP8266 (0) 官方API

    http://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/readme.html 0 简单的连接到WIFI #include <ES ...

  9. Arduino IDE for ESP8266教程(二) 创建WIFI AP模式

    创建WIFI热点 #include <ESP8266WiFi.h> void setup() { Serial.begin ( 115200 ); Serial.println(" ...

  10. Emoji表情符号在MySQL数据库中的存储

    文章转自https://www.jianshu.com/p/20740071d854 在Android手机或者iPhone的各种输入法键盘中,会自带一些Emoji表情符号,如IPhone手机系统键盘包 ...