Shell字符串操作

1 字符串的属性

概要示例: 下面我们来看看如何判断字符的类型。

 1 // 数字或者数字组合(能够返回结果,即程序退出状态是0,说明属于这种类型,反之不然)
 2 $ i=5;j=9423483247234;
 3 $ echo $i | grep [0-9]*
 4 5
 5 $ echo $j | grep [0-9]*
 6 9423483247234
 7 $ echo $j | grep [0-9]* >/dev/null
 8 $ echo $?
 9 0
10 // 字符组合(小写字母、大写字母、两者的组合)
11 $ c="A"; d="fwefewjuew"; e="fewfEFWefwefe"
12 $ echo $c | grep [A-Z]
13 A
14 $ echo $d | grep "[a-z]*"
15 fwefewjuew
16 $ echo $e | grep "[a-zA-Z]*"
17 fewfEFWefwefe
18 // 字母和数字的组合
19 $ ic="432fwfwefeFWEwefwef"
20 $ echo $ic | grep "[0-9a-zA-Z]*"
21 432fwfwefeFWEwefwef
22 // 空格或者Tab键等
23 $ echo " " | grep " "
24   
25 $ echo -e "\t" | grep "[[:space:]]" #[[:space:]]会同时匹配空格和TAB键
26  
27 $ echo -e " \t" | grep "[[:space:]]"
28  
29 $ echo -e "\t" | grep "<tab>" #<tab>为在键盘上按下TAB键,而不是字符<tab>
30 // 匹配邮件地址
31 $ echo "test2007@lzu.cn" | grep "[0-9a-zA-Z\.]*@[0-9a-zA-Z\.]"
32 test2007@lzu.cn
33 // 匹配URL地址(以http链接为例)
34 $ echo "http://news.lzu.edu.cn/article.jsp?newsid=10135" | grep "http://[0-9a-zA-Z\./=?]*"
35 http://news.lzu.edu.cn/article.jsp?newsid=10135

说明:
[1] /dev/null和/dev/zero是非常有趣的两个设备,它们都犹如一个黑洞,什么东西掉进去都会消失殆尽;后者则是一个能源箱,你总能从那里取到0,直到你退出。
[2] [[:space:]]是grep用于匹配空格或者TAB键类型字符串的一种标记,其他类似的标记请查看grep的帮助,man grep。
[3] 上面都是用grep来进行模式匹配,实际上sed, awk都可以用来做模式匹配,关于匹配中用到的正则匹配模式知识,大家可以参考正则匹配模式,更多相关资料请看参考资料。
[4] 如果仅仅想判断字符串是否为空,即判断字符串的长度是否为零,那么可以简单的通过test命令的-z选项来判断,具体用法见test命令,man test.

概要示例: 判断字符是否可打印?如何控制字符在终端的显示。

 

 1 // 用grep判断某个字符是否为可打印字符
 2 $ echo "\t\n" | grep "[[:print:]]"
 3 \t\n
 4 $ echo $?
 5 0
 6 $ echo -e "\t\n" | grep "[[:print:]]"
 7 $ echo $?
 8 1
 9 // 用echo的-e选项在屏幕控制字符显示位置、颜色、背景等
10 $ echo -e "\33[31;40m" #设置前景色为黑色,背景色为红色
11 $ echo -e "\33[11;29H Hello, World\!" #在屏幕的第11行,29列开始打印字符串Hello,World!
12 // 在屏幕的某个位置动态显示当前系统时间
13 $ while :; do echo -e "\33[11;29H "$(date "+%Y-%m-%d %H:%M:%S"); done
14 // 用col命令过滤掉某些控制字符,在处理诸如script,screen等截屏命令的输出结果时,很有用
15 $ screen -L
16 $ cat /bin/cat
17 $ exit
18 $ cat screenlog.0 | col -b   # 把一些控制字符过滤后,就可以保留可读的操作日志

 

 

2 字符串的长度

概要示例: 除了组成字符串的字符类型外,字符串还有哪些属性呢?组成字符串的字符个数。下面我们来计算字符串的长度,即所有字符的个数,并简单介绍几种求字符串中指定字符个数的方法。

 

 1 // 计算某个字符串的长度,即所有字符的个数[这计算方法是五花八门,择其优着而用之]
 2 $ var="get the length of me"
 3 $ echo ${var}     # 这里等同于$var
 4 get the length of me
 5 $ echo ${#var}
 6 20
 7 $ expr length "$var"
 8 20
 9 $ echo $var | awk '{printf("%d\n", length($0));}'
10 20
11 $ echo -n $var |  wc -c
12 20
13 // 计算某些指定一个字符或者多个字符的个数
14 $ echo $var | tr -cd g | wc -c
15 2
16 $ echo -n $var | sed -e 's/[^g]//g' | wc -c
17 2
18 $ echo -n $var | sed -e 's/[^gt]//g' | wc -c
19 5
20 // 如果要统计单词个数,更多相关信息见《shell编程之数值计算》之 _单词统计_ 实例。
21 $ echo $var | wc -w
22 5
23 $ echo "$var" | tr " " "\n" | grep get | uniq -c
24 1
25 $ echo "$var" | tr " " "\n" | grep get | wc -l
26 1

 

1 stringZ=abcABC123ABCabc
2 echo `expr "$stringZ" : '.*'`    # 15

说明:

${}操作符在Bash里头一个“大牛”,能胜任相当多的工作,具体就看看网中人的《shell十三问》之《Shell十三问》之"$(( )) 與 $( ) 還有${ } 差在哪?" 吧。

在一个文本文件的段落之间插入空行

 

 1 #!/bin/bash
 2 # paragraph-space.sh
 3  
 4 # 在一个单倍行距的文本文件中插入空行.
 5 # Usage: $0 <FILENAME
 6   
 7 MINLEN=45        # 可能需要修改这个值.
 8 #  假定行的长度小于$MINLEN所指定的长度的时候
 9 #+ 才认为此段结束.
10  
11 while read line  # 提供和输入文件一样多的行...
12 do
13    echo "$line"   # 输入所读入的行本身.
14   
15    len=${#line}
16    if [ "$len" -lt "$MINLEN" ]
17      then echo    # 在短行(译者注: 也就是小于$MINLEN个字符的行)后面添加一个空行.
18    fi 
19 done
20   
21 exit 0

 

索引

expr index $string $substring

在字符串$string中所匹配到的$substring第一次所出现的位置.

1 stringZ=abcABC123ABCabc
2 echo `expr index "$stringZ" C12`             # 6
3                                             # C 字符的位置.
4  
5 echo `expr index "$stringZ" 1c`              # 3
6  # 'c' (in #3 position) matches before '1'.

这与C语言中的strchr()函数非常相似.

 

3 字符串的存储

通过字符在串中的位置来呈现它
这样我们就可以通过指定位置来找到某个子串。这在c语言里头通常可以利用指针来做。而在shell编程中,有很多可用的工具,诸如expr,awk都提供了类似的方法来实现子串的查询动作。两者都几乎支持模式匹配(match)和完全匹配(index)。这在后面的字符串操作中将详细介绍。
匹配字符串开头的子串长度
expr match "$string" '$substring'
        $substring是一个正则表达式.
expr "$string" : '$substring'
        $substring是一个正则表达式.

1 stringZ=abcABC123ABCabc
2 #       |------|
3  
4 echo `expr match "$stringZ" 'abc[A-Z]*.2'`   # 8
5 echo `expr "$stringZ" : 'abc[A-Z]*.2'`       # 8

3.2 根据某个分割符来取得字符串的各个部分

 1 //1. bash提供的数组数据结构,它是以数字为下标的,和C语言从0开始的下标一样
 2 $ var="get the length of me"
 3 $ var_arr=($var)    #这里把字符串var存放到字符串数组var_arr中了,默认以空格作为分割符
 4 $ echo ${var_arr[0]} ${var_arr[1]} ${var_arr[2]} ${var_arr[3]} ${var_arr[4]}
 5 get the length of me
 6 $ echo ${var_arr[@]}    #这个就是整个字符串所有部分啦,这里可以用*代替@,下同
 7 get the length of me
 8 $ echo ${#var_arr[@]}    #记得上面求某个字符串的长度么,#操作符,如果想求某个数组元素的字符串长度,那么就把@换成下标吧
 9 5
10 // 你也可以直接给某个数组元素赋值
11 $ var_arr[5]="new_element"
12 $ echo ${var_arr[5]}
13 6
14 $ echo ${var_arr[5]}
15 new_element
16 // bash里头实际上还提供了一种类似于“数组”的功能,即"for i in 用指定分割符分开的字符串" 的用法
17 // 即,你可以很方便的获取某个字符串的某个部分
18 $  for i in $var; do echo -n $i" "; done;
19 get the length of me
20  
21 //2. awk里头的数组,注意比较它和bash提供的数组的异同
22 // split把一行按照空格分割,存放到数组var_arr中,并返回数组的长度。注意:这里的第一个元素下标不是0,而是1
23 $ echo $var | awk '{printf("%d %s\n", split($0, var_arr, " "), var_arr[1]);}'
24 5 get
25 // 实际上,上面的操作很类似awk自身的行处理功能:awk默认把一行按照空格分割为多个域,并可以通过$1,$2,$3...来获取,$0表示整行
26 // 这里的NF是该行的域的总数,类似于上面数组的长度,它同样提供了一种通过“下标”访问某个字符串的功能
27 $ echo $var | awk '{printf("%d | %s %s %s %s %s | %s\n", NF, $1, $2, $3, $4, $5, $0);}'
28 5 | get the length of me | get the length of me
29 // awk的“数组”功能何止于此呢,看看它的for引用吧,注意,这个和bash里头的for不太一样,i不是元素本身,而是下标
30 $ echo $var | awk '{split($0, var_arr, " "); for(i in var_arr) printf("%s ",var_arr);}'
31 get the length of me
32 $ echo $var | awk '{split($0, var_arr, " "); for(i in var_arr) printf("%s ",i);}'
33 1 2 3 4 5
34 // awk还有更“厉害”的处理能力,它的下标可以不是数字,而可以是字符串,从而变成了“关联”数组,这种“关联”的作用在某些方便将让我们非常方便
35 // 比如,我们这里就实现一个非凡的应用,把某个文件中的某个系统调用名替换成地址,如果你真正用起它,你会感慨它的“鬼斧神工”的。
36 // 这就是我在一个场合最好才发现的随好的实现方案:有兴趣看看awk手册帖子中我在3楼回复的实例吧。
37 $ cat symbol
38 sys_exit
39 sys_read
40 sys_close
41 $ ls /boot/System.map*
42 $ awk '{if(FILENAME ~ "System.map") map[$3]=$1; else {printf("%s\n", map[$1])}}' /boot/System.map-2.6.20-16-generic symbol
43 c0129a80
44 c0177310
45 c0175d80
46 // 另外,awk还支持删除某个数组元素,如果你不用了就可以用delete函数给删除掉。如果某些场合有需要的话,别忘了awk还支持二维数组。

 


取子串
概要示例:取子串的方法主要有:直接到指定位置求子串,字符匹配求子串。
${string:position}
在$string中从位置$position开始提取子串.
如果$string是"*"或者"@", 那么将会提取从位置$position开始的位置参数.[1]
${string:position:length}
在$string中从位置$position开始提取$length长度的子串.
如果$string参数是"*"或"@", 那么将会从$position位置开始提取$length个位置参数, 但是由于可能没有$length个位置参数了, 那么就有几个位置参数就提取几个位置参数.
expr substr $string $position $length
在$string中从$position开始提取$length长度的子串.
expr match "$string" '\($substring\)'
从$string的开始位置提取$substring,$substring是正则表达式.
expr "$string" : '\($substring\)'
从$string的开始位置提取$substring,$substring是正则表达式.
expr match "$string" '.*\($substring\)'
从$string的结尾提取$substring,$substring是正则表达式.
expr "$string" : '.*\($substring\)'
从$string的结尾提取$substring,$substring是正则表达式.

 1 // 按照位置取子串,比如从什么位置开始,取多少个字符
 2 $ var="get the length of me"
 3 $ echo ${var:0:3}
 4 get
 5 $ echo ${var:(-2)}   # 方向相反呢
 6 me
 7 $ echo `expr substr "$var" 5 3` #记得把$var引起来,否则expr会因为空格而解析错误
 8 the
 9 $ echo $var | awk '{printf("%s\n", substr($0, 9, 6))}'
10 length
11  
12 // 匹配字符求子串
13 $ echo ${var%% *} #从右边开始计算,删除最左边的空格右边的所有字符
14 get
15 $ echo ${var% *} #从右边开始计算,删除第一个空格右边的所有字符
16 get the length of
17 $ echo ${var##* }  #从左边开始计算,删除最右边的空格左边的所有字符
18 me
19 $ echo ${var#* }  #从左边开始计算,删除第一个空格左边的所有字符
20 the length of me
21  
22 $ echo $var | awk '{printf("%s\n", $1);}' # awk把$var按照空格分开为多个变量,依次为$1,$2,$3,$4,$5
23 get
24 $ echo $var | awk '{printf("%s\n", $5);}'
25 me
26  
27 $ echo $var | cut -d" " -f 5  #差点把cut这个小东西忘记啦,用起来和awk类似, -d指定分割符,如同awk用-F指定分割符一样,-f指定“域”,如同awk的$数字。
28  
29 $ echo $var | sed 's/ [a-z]*//g'  #删除所有 空格+字母串 的字符串,所以get后面的全部被删除了
30 get
31 $ echo $var | sed 's/[a-z]* //g'
32 me
33  
34 $ echo $var | tr " " "\n" | sed -n 1p #sed有按地址(行)打印(p)的功能,记得先用tr把空格换成行号
35 get
36 $ echo $var | tr " " "\n" | sed -n 5p
37 me
38  
39 // tr也可以用来取子串哦,它也可以类似#和%来“拿掉”一些字符串来实现取子串
40 $ echo $var | tr -d " "
41 getthelengthofme
42 $ echo $var | tr -cd "[a-z]" #把所有的空格都拿掉了,仅仅保留字母字符串,注意-c和-d的用法
43 getthelengthofme

 

字符串拆分

方法一: 利用shell 中 变量 的字符串替换(拆分字符串)

#!/bin/bash
 
string="hello,shell,split,test"  
array=(${string//,/ })  
 
for var in ${array[@]}
do
   echo $var
done 

 

方法二: 设置分隔符,通过 IFS 变量

#!/bin/bash
 
string="hello,shell,split,test"  
 
#对IFS变量 进行替换处理
OLD_IFS="$IFS"
IFS=","
array=($string)
IFS="$OLD_IFS"
 
for var in ${array[@]}
do
   echo $var
done

 

方法三: 利用tr 指令实现字符替换

#!/bin/bash
 
string="hello,shell,split,test"  
array=(`echo $string | tr ',' ' '` )  
 
for var in ${array[@]}
do
   echo $var
done 
 

 

 字符串拼接(连接字符串)

 

方法一:

value1=home
value2=${value1}"="
echo $value2

 

方法二:

var1=/etc/
var2=yum.repos.d/
var3=${var1}${var2}
echo $var3

 

 

删除字符串中最后一个字符

string1=123456

string1=${string1%?}
echo $string1
 

 

Ref:

http://blog.chinaunix.net/uid-124706-id-3475936.html

 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


系ubuntu 下面打开终端输入:sudo apt-get install sendmail一般就安装完成噶啦跟住进入 /etc/mail/目录输入:m4 sendmail.mc &gt; sendmail.cf意思系跟住.mc文件 生成 sendmial.cf文件输入呢个命令:ps aux | g
依家我有1个软件goagent目录(大家懂得) 放在/home/gateman/Programs/ 下 1. proxy.py 入面有1个 proxy.py 文件 放在/home/gateman/Programs/goagent/local/ 入面 2.breakwall.sh 我在 proxy.p
其实我想讲的是 cp -L关于-L参数的解释:-L, --dereference always follow symbolic links in SOURCE意思是如果复制目标是1个软链接,则复制链接的目标 不是链接本身做个例子: 例如 ~/tmp/fo1 入面有1个c.txt 文件 和 指向他的软
原地址:http://www.rjgc.net/control/content/content.php?nid=4418 1、将文件checkout到本地目录svn checkout path(path是服务器上的目录)例如:svn checkout svn://192.168.1.1/pro/do
chroot,即 change root directory (更改 root 目录)。在 linux 系统中,系统默认的目录结构都是以 `/`,即是以根 (root) 开始的。而在使用 chroot 之后,系统的目录结构将以指定的位置作为 `/` 位置。实例:用live CD ubuntu假设你的
简单解析下, stdin就是标准输入, stdout就是标准。举个例子, 在当前我要打包1个文件夹 /var/log/ 到当前目录下,并用zip压缩,那么我们可以分步执行#tar -cvf log.tar /var/log/#zip -r log.tar.zip log.tar#rm -rf log
转自:http://man.ddvip.com/linux/Mandrakelinuxref/process-priority.html系统中运行的每个进程都有一个优先级(亦称“nice 值”),其范围从 -20 (最高优先级)到 19 (最低优先级)。默认情况下,进程的优先级是 0 (“基本”调度
str=&quot;/home/gateman&quot; if [ ${str:0:1} = &quot;/&quot; ]; then echo &quot;yes&#39;fi ${str:0:1} 中0表示从第几个字符开始,1表示截取多长
转自:http://kwokchivu.blog.51cto.com/1128937/694347 在RedHat系统下用usermod 命令可把某用户添加进多个附属组,默认情况下,一次性添加多个附属组可用以下方式来添加: usermod -G 附属组1,附属组2,...,附属组X 用户名 但在添加
有个文件 test.txt 内容如下:bash-3.00$ cat test.txt user user user_hiuser #注:呢行系空行T JGATEMANGATTTTTEMANGABBEMANAAABbash-3.00$下面介绍下常用的通配符 配合grep 命令:1. &quot;.&q
linux系统为每1个文件都分配有i索引节点(inode),系统根据呢d节点从磁盘找出数据。 一般来讲,每1个文件名(包含全路径)实际上都链接住1个i索引节点。inode实际上系乜咧? 其实可以算系1个指向磁盘具体位置(柱面,扇区之类)的指针, 系统分析某个文件的inode,得出磁盘柱面,扇区等数据
grep 可以立即为筛选, 一般的用法系 grep + 要查询的字段 + 文件(或者内容 例如| 传递既内容)1.grep + 要查询的字段 + 文件gateman@GPC:~/shell/SQL_GSI$ grep OID a.sqlWHERE OID=@BuildNOWHERE OID INWH
原文转自:http://www.ibm.com/developerworks/cn/linux/l-cn-vimcolumn/index.html开始之前人类大脑对文字的处理是平面式的,所以我们浏览文章、查找资料或者重构代码,要么是横向读,要么是纵向读,要么使用搜索功能,将文字作为一个平面整体。而在
PS:偶很喜欢用scp这个命令来传输数据。scp命令跟cp命令类似,只不过cp命令是在同一台机器上用的,scp是在两台机器上复制传输数据的命令。scp实质相当于利用SSH协议来传输数据的cp命令。 用法举例: 1、复制远程服务器的文件到本地: scp -P888 root@120.18.50.33:
打开终端,进入/bin/ls 一下会见到 bash sh 呢两个文件。其实距地系两个唔同既shell 解析器。如果在脚本a.sh 开头写入#!/bin/sh那么执行./a.sh 时候 就相当于 sh a.sh同理 开头写入#!/bin/bash执行./a.sh 时候 就相当于 bash a.sh如果
find查找文件的时候排除某个或几个文件或目录转自:http://www.cnblogs.com/starspace/archive/2008/10/20/1315380.html比如要在/usr/sam目录下查找不在dir1子目录之内的所有文件find /usr/sam -path &quot;/
假设有变量 var=http://www.google.com/test.htm一 # 号截取,删除左边字符,保留右边字符。echo ${var#*//}其中 var 是变量名,# 号是运算符,*// 表示从左边开始删除第一个 // 号及左边的所有字符即删除 http://结果是 :www.goog
转自: http://edyfox.codecarver.org/html/_vimrc_for_beginners.htmlVIM 中可供用户定制的选项非常非常多,作为初学者,我们没有必要了解这么多东西。下面,滇狐简单列出了一些最常用的配置项,大家可以根据自己的需要将这些内容添加到自己的 .vim
转自:http://www.einit.com/user1/11/archives/2006/3603.htmlUnix/Linux下一般想让某个程序在后台运行,很多都是使用 &amp; 在程序结尾来让程序自动运行。比如我们要运行mysql在后台: /usr/local/mysql/bin/mysq
首先, mount是类unix系统, 挂载设备到1个文件夹的操作命令, 注意系设备阿正常来讲,mount 是不能挂在文件夹到文件夹的。例如, 在我的~/tmp/ 目录中有两个文件夹fo1 fo2其中fo1 中有3个文件a.txt b.txt c.txt fo2 有4个 e.txt d.txt e.t