在日常运维工作中,经常会碰到需要在一个字符串中截取我们需要的某些字符的需求,之前介绍了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. Mvc检查图片格式后上传

    /// <summary> /// 检查是否文件是否图片并保存 /// </summary> /// <param name="file">文件 ...

  2. Maven将依赖包、jar/war包及配置文件输出到指定目录

    使用Maven插件将依赖包 jar包 war包及配置文件输出到指定目录 写在前面 ​ 最近遇到一个朋友遇到一个项目需要将 maven 的依赖包和配置文件分开打包然后用脚本执行程序.这样的好处在于可以随 ...

  3. January 07th, 2018 Week 01st Sunday

    To remember is to disengage from the present. 铭记过去就是放弃当下. To remember the past doesn't mean we would ...

  4. 对JavaScript垃圾回收机制的理解?

    (1)标记清除(Mark and sweep) 这是JavaScript最常见的垃圾回收方式,当变量进入执行环境的时候,比如函数中声明一个变量,垃圾回收器将其标记为”进入环境”,当变量离开环境的时候( ...

  5. 转载 Spring详细教程

    SpringMVC学习笔记---- 一.SpringMVC基础入门,创建一个HelloWorld程序 1.首先,导入SpringMVC需要的jar包. 2.添加Web.xml配置文件中关于Spring ...

  6. keystore密钥文件使用的算法-PBKDF2WithHmacSHA1 和Scrypt

    PBKDF2 简单而言就是将salted hash进行多次重复计算,这个次数是可选择的.如果计算一次所需要的时间是1微秒,那么计算1百万次就需要1秒钟.假如攻击一个密码所需的rainbow table ...

  7. Spring配置跨域请求

    本文主要是Spring+SpringMVC+MyBatis/MyBatis Plus框架环境,包括SpringBoot同样适用. 1.编写拦截器 package com.interceptor; im ...

  8. 个人向 - vscode插件记录

    现在用的编译器的是vscode,本身这个编译器很小,很多功能都没有,需要自己下载一些插件来完善功能,不知不觉下载的插件也有三十多个了,感觉需要记录一下. tips:1. vscode插件的安装位置:’ ...

  9. 理解socket.io(一)---相关的API

    理解socket.io(一)---相关的API 1. 什么是Socket.IO?Socket.IO是node.js的一个模块,它用于浏览器与服务端之间实时通信.它提供了服务器和客户端的组件,只需一个模 ...

  10. VUE2 第五天学习--过渡效果

    阅读目录 1.理解VUE---过渡效果 回到顶部 1.理解VUE---过渡效果 1. 过渡的-css-类名会有4个(css) 类名在 enter/leave 在过渡中切换.1. v-enter: 进入 ...