【问题标题】:How to pull a string apart by its contents如何通过其内容将字符串拉开
【发布时间】:2019-05-20 05:13:53
【问题描述】:

我有一个我想要操作的通用模式的字符串。我希望能够将字符串5B299 转换为5B300(将最后一个数字加一)。

我想避免盲目地按索引拼接字符串,因为第一个数字和字母可以改变大小。本质上,我希望能够在第一个字符之后获取所有内容的全部值,将其递增一个,然后重新附加它。

到目前为止,我在网上找到的唯一东西向我展示了如何通过分隔符进行剪切,但我没有常量分隔符。

【问题讨论】:

  • 你尝试了什么?将那些失败的尝试发布到问题中。您是否声称只应考虑最后 3 个字符?
  • @Inian 我没有失败的尝试,我对命令行太陌生了,还没有为自己尝试过任何东西。它不完全是三个数字,它可能是一个数字或五个数字,具体取决于它增加了多少次。
  • 请不要让我们猜测您输入的样本的所有细节,提供一组合理(但很少)的样本。祝你好运。

标签: bash shell


【解决方案1】:

您可以使用 bash shell 支持的正则表达式功能及其支持基本扩展正则表达式匹配 (ERE) 的 ~ 构造。您需要做的就是定义一个正则表达式并处理捕获的组以获取结果字符串

str=5B299
re='^(.*[A-Z])([0-9]+)$' 

现在使用~ 运算符进行正则表达式匹配。如果正则表达式匹配成功,~ 运算符将使用捕获的组填充数组 BASH_REMATCH。第一部分(示例中为5B)将存储在索引0 中,下一部分存储在1 中。我们使用$((..)) 运算符增加索引1 处的值。

if [[ $str =~ $re ]]; then
    result="${BASH_REMATCH[1]}$(( BASH_REMATCH[2] + 1 ))"
    printf '%s\n' "$result"
fi

正则表达式的 POSIX 版本,没有语言环境依赖,将使用字符类而不是范围表达式

posix_re='^(.*[[:alpha:]])([[:digit:]]+)$'

【讨论】:

    【解决方案2】:

    您可以使用用于字符串索引的 bash parameter-expansion 以及 POSIX 算术运算符相当轻松地完成您正在尝试的事情。例如你可以这样做:

    #!/bin/bash
    
    [ -z "$1" ] && {    ## validate at least 1 argument provided
        printf "error: please provide a number.\n" >&2
        exit 1
    }
    
    [[ $1 =~ [^0-9][^0-9]* ]] && {  ## validate all digits in argument
        printf "error: input contains non-digit characters.\n" >&2
        exit 1
    }
    
    suffix=${1:1}           ## take all character past 1st as suffix
    suffix=$((suffix + 1))  ## increment suffix by 1
    
    result=${1:0:1}$suffix  ## append suffent to orginal 1st character
    echo "$result"          ## output
    
    exit 0
    

    这将保留第一个字符,同时将剩余字符递增1,然后再次加入原始第一个数字,同时验证输入仅包含数字,例如

    使用/输出示例

    $ bash prefixsuffix.sh
    error: please provide a number.
    
    $ bash prefixsuffix.sh 38a900
    error: input contains non-digit characters.
    
    $ bash prefixsuffix.sh 38900
    38901
    
    $ bash prefixsuffix.sh 39999
    310000
    

    检查一下,让我知道这是否是您的意图。

    【讨论】:

      【解决方案3】:

      您可以将sedawk 结合使用:

      increment() {
         echo $1 | sed -r 's/([0-9]+[a-zA-Z]+)([0-9]+)/\1 \2/' | awk '{printf "%s%d", $1, ++$2}'
      }
      
      echo $(increment "5B299")
      echo $(increment "127ABC385")
      echo $(increment "7cf999")
      

      输出:

      5B300
      127ABC386
      7cf1000
      

      【讨论】:

      • 我收到错误 sed: illegal option -- r,在 macOS 10.15 上运行 Bash 3.2.57。
      • @Ricky 你需要在你的系统上安装gnu-sed stackoverflow.com/a/46859893/3920623
      • 哦,Mac似乎有更简单的解决方案,只需将-r选项更改为-E就可以了。
      猜你喜欢
      • 1970-01-01
      • 2012-03-16
      • 2010-11-28
      • 2013-06-23
      • 2020-10-20
      • 1970-01-01
      • 1970-01-01
      • 2011-07-11
      • 2012-07-24
      相关资源
      最近更新 更多