shell字符串操作技巧

操作字符串
--------------
Bash支持超多的字符串操作,操作的种类和数量令人惊异.但不幸的是,这些工具缺乏集中性.
一些是参数替换的子集,但是另一些则属于UNIX的expr命令.这就导致了命令语法的不一致和
功能的重叠,当然也会引起混乱.

1、字符串长度
  ${#string}
  expr length $string
  expr "$string" : '.*'
  
  stringZ=abcABC123ABCabc
  
  echo ${#stringZ}                 
  echo `expr length $stringZ`      
  echo `expr "$stringZ" : '.*'`    

2、从字符串开始的位置匹配子串的长度
  expr match "$string" '$substring' $substring是一个正则表达式
  expr "$string" : '$substring'  $substring是一个正则表达式
  
  stringZ=abcABC123ABCabc
  echo `expr match "$stringZ" 'abc[A-Z]*.2'`   
  echo `expr "$stringZ" : 'abc[A-Z]*.2'`       
3、索引
	expr index $string $substring 匹配到子串的第一个字符的位置.
	stringZ=abcABC123ABCabc
	echo `expr index "$stringZ" C12`             

	echo `expr index "$stringZ" 1c`              
	# 'c' (in #3 position) matches before '1'.

	在C语言中最近的等价函数为strchr().
提取子串
		${string:position}
		在string中从位置$position开始提取子串.
		如果$string为"*"或"@",那么将提取从位置$position开始的位置参数,[1]
	${string:position:length}
		在string中从位置$position开始提取$length长度的子串.

################################StartScript######################################
stringZ=abcABC123ABCabc
#       0123456789.....
#       0-based indexing.

echo ${stringZ:0}                            # abcABC123ABCabc
echo ${stringZ:1}                            # bcABC123ABCabc
echo ${stringZ:7}                            # 23ABCabc
echo ${stringZ:7:3}                          # 23A
                                             # 3个字符长度的子串.
# 有没有可能从字符结尾开始,反向提取子串?
    
echo ${stringZ:-4}                           # abcABC123ABCabc
# 以${parameter:-default}方式,默认是提取完整地字符串.
# 然而 . . .
echo ${stringZ:(-4)}                         # Cabc 
echo ${stringZ: -4}                          # Cabc
# 现在,它可以工作了.
# 使用圆括号或者添加一个空格来转义这个位置参数.

如果$string参数为"*"或"@",那将最大的提取从$position开始的$length个位置参数.

    echo ${*:2}          # Echo出第2个和后边所有的位置参数.
    echo ${@:2}          # 与前边相同.
    echo ${*:2:3}        # 从第2个开始,Echo出后边3个位置参数.
    expr substr $string $position $length
    	在string中从位置$position开始提取$length长度的子串.
    stringZ=abcABC123ABCabc
    #       123456789......
    #       1-based indexing.
    
    echo `expr substr $stringZ 1 2`              # ab
    echo `expr substr $stringZ 4 3`              # ABC
    
    expr match "$string" '\($substring\)'
    	从$string的开始位置提取$substring,$substring是一个正则表达式.
    
    expr "$string" : '\($substring\)'
    	从$string的开始位置提取$substring,$substring是一个正则表达式.
    stringZ=abcABC123ABCabc
    
    echo `expr match "$stringZ" '\(.[b-c]*[A-Z]..[0-9]\)'`   # abcABC1
    echo `expr "$stringZ" : '\(.[b-c]*[A-Z]..[0-9]\)'`       # abcABC1
    echo `expr "$stringZ" : '\(.......\)'`                   # abcABC1
    # All of the above forms give an identical result.
子串削除
	${string#substring}
		 从$string的左边截掉第一个匹配的$substring
	${string##substring}
		 从$string的左边截掉最后一个个匹配的$substring
	stringZ=abcABC123ABCabc
	#       |----|
	#       |----------|
	
	echo ${stringZ#a*C}      # 123ABCabc
	# 截掉'a'和'C'之间最近的匹配.
	
	echo ${stringZ##a*C}     # abc
	# 截掉'a'和'C'之间最远的匹配. 
		
	
	${string%substring}
		 从$string的右边截掉第一个匹配的$substring
	${string%%substring}
		 从$string的右边截掉最后一个匹配的$substring

	stringZ=abcABC123ABCabc
	#                    ||
	#        |------------|
	
	echo ${stringZ%b*c}      # abcABC123ABCa
	# 从$stringZ的后边开始截掉'b'和'c'之间的最近的匹配
	
	echo ${stringZ%%b*c}     # a
	# 从$stringZ的后边开始截掉'b'和'c'之间的最远的匹配

Example 9-11 利用修改文件名,来转换图片格式
################################StartScript######################################
 #!/bin/bash
 #  cvt.sh:
 #  把一个目录下的所有MacPaint格式的图片文件都转换为"pbm"格式的图片文件.
 
 #  使用来自"netpbm"包的"macptopbm"程序,
 #+ 这个程序主要是由Brian Henderson(bryanh@giraffe-data.com)来维护的.
 #  Netpbm是大多数Linux发行版的标准部分.
 
 OPERATION=macptopbm
 SUFFIX=pbm          # 新的文件名后缀
 
 if [ -n "$1" ]
 then
   directory=$1      # 如果目录名作为第1个参数给出...
 else
   directory=$PWD    # 否则使用当前的工作目录.
 fi  
   
 #  假设在目标目录中的所有文件都是MacPaint格式的图片文件,
 #+ 以".mac"为文件名的后缀.
 
 for file in $directory/*    # Filename globbing.
 do
   filename=${file%.*c}      #  去掉文件名的".mac"后缀
                             #+ ('.*c' matches everything
                             #+ ('.*c' 将匹配'.'和'c'之间的任何字符串).

   $OPERATION $file > "$filename.$SUFFIX"
                             # 转换为新的文件名.
   rm -f $file               # 转换完毕后删除原有的文件.
   echo "$filename.$SUFFIX"  # 从stdout输出反馈.
 done
 
 exit 0
 

 #  修改这个脚本,让他只转换以".mac"为后缀的文件.
################################EndScript#######################################
		一个简单的模拟getopt命令的办法就是使用子串提取结构.
Example 9-12 模仿getopt命令
################################StartScript######################################
 #!/bin/bash
 # getopt-simple.sh
 # Author: Chris Morgan
 # 授权使用在ABS Guide中.
 
 
 getopt_simple()
 {
     echo "getopt_simple()"
     echo "Parameters are '$*'"
     until [ -z "$1" ]
     do
       echo "Processing parameter of: '$1'"
       if [ ${1:0:1} = '/' ]
       then
           tmp=${1:1}               # 去掉开头的'/' . . .
           parameter=${tmp%%=*}     # 提取名字.
           value=${tmp##*=}         # 提取值.
           echo "Parameter: '$parameter', value: '$value'"
           eval $parameter=$value
       fi
       shift
     done
 }
 
 # 传递所有的选项到getopt_simple().
 getopt_simple $*
 
 echo "test is '$test'"
 echo "test2 is '$test2'"
 
 exit 0
 
 ---
 
 sh getopt_example.sh /test=value1 /test2=value2
 
 Parameters are '/test=value1 /test2=value2'
 Processing parameter of: '/test=value1'
 Parameter: 'test', value: 'value1'
 Processing parameter of: '/test2=value2'
 Parameter: 'test2', value: 'value2'
 test is 'value1'
 test2 is 'value2'
################################EndScript#######################################
子串替换
	${string/substring/replacement}
		使用$replacement来替换第一个匹配的$substring.
	${string//substring/replacement}
		使用$replacement来替换所有匹配的$substring.

	1 stringZ=abcABC123ABCabc
	2 
	3 echo ${stringZ/abc/xyz}           # xyzABC123ABCabc
	4                                   # 用'xyz'来替换第一个匹配的'abc'.
	5 
	6 echo ${stringZ//abc/xyz}          # xyzABC123ABCxyz
	7                                   # 用'xyz'来替换所有匹配的'abc'.

	${string/#substring/replacement}
		如果$substring匹配$string的开头部分,那么就用$replacement来替换$substring.
	${string/%substring/replacement}
		如果$substring匹配$string的结尾部分,那么就用$replacement来替换$substring.
	1 stringZ=abcABC123ABCabc
	2 
	3 echo ${stringZ/#abc/XYZ}          # XYZABC123ABCabc
	4                                   # 用'XYZ'替换开头的'abc'
	5 
	6 echo ${stringZ/%abc/XYZ}          # abcABC123ABCXYZ
	7                                   # 用'XYZ'替换结尾的'abc'


9.2.1 使用awk来操作字符串
~~~~~~~~~~~~~~~~~~~~~~~~~
Bash脚本也可以使用awk来操作字符串.
Example 9-13 提取字符串的一种可选的方法
################################StartScript######################################
 #!/bin/bash
 # substring-extraction.sh
 
 String=23skidoo1
 #      012345678    Bash
 #      123456789    awk
 # 注意,对于awk和Bash来说,它们使用的是不同的string索引系统:
 # Bash的第一个字符是从'0'开始记录的.
 # Awk的第一个字符是从'1'开始记录的. 
 
 echo ${String:2:4} # 位置3 (0-1-2), 4 个字符长
                                          # skid
 
 # awk中等价于${string:pos:length}的命令是substr(string,pos,length).
 echo | awk '
 { print substr("'"${String}"'",3,4)      # skid
 }
 '
 #  使用一个空的"echo"通过管道给awk一个假的输入,
 #+ 这样可以不用提供一个文件名.

 

posted @ 2015-12-22 17:49  开心玩数据  阅读(4735)  评论(0编辑  收藏  举报