zoukankan      html  css  js  c++  java
  • 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一个假的输入,
     #+ 这样可以不用提供一个文件名.
    
  • 相关阅读:
    JS站点
    1011 World Cup Betting (20分)
    1007 Maximum Subsequence Sum (25分)(动态规划DP)
    1006 Sign In and Sign Out (25分)
    1005 Spell It Right (20分)
    1004 Counting Leaves (30分)(DFS)
    1003 Emergency (25分)(Dijkstra算法)
    1002 A+B for Polynomials (25分)
    1001 A+B Format (20分)
    canvas
  • 原文地址:https://www.cnblogs.com/tychyg/p/5067453.html
Copyright © 2011-2022 走看看