【问题标题】:Get digit from filename immediately preceeding file extension, with other digits in filename从文件名中获取紧跟在文件扩展名之前的数字,以及文件名中的其他数字
【发布时间】:2013-09-04 02:20:14
【问题描述】:

我正在尝试提取 bash 脚本中文件扩展名之前的最后一个数字。所以格式会有所不同,但它会是数字和字母的某种组合,最后一个字符将始终是数字。我需要提取这些数字并将它们存储在一个变量中。

格式一般为:

sdflkej10_sdlkei450_sdlekr_1.txt

我只想将最后一个数字 1 存储到变量中。

我将使用它来遍历大量文件,最后一个数字将变为两位数和三位数。

所以对于这个文件:

kej10_sdlkei450_sdlekr_310.txt

我需要返回 310。

字母数字字符和下划线的数量因每个文件而异,但我想要的数字始终位于 .txt 扩展名之前和下划线之后。

我试过了:

bname=${f%%.*}
number=$(echo $bname | tr -cd '[[:digit:]]') 

但这会返回所有数字。

如果我尝试

number = $(echo $(bname -2) it changes the number it returns.

我遇到的问题主要与可变性有关,以及我被要求在 bash 中执行此操作的事实。任何帮助将不胜感激。

【问题讨论】:

  • 当你说你必须“在 bash 中做”时,这是否意味着你不能使用命令行版本的实用程序,如 perl 或 sed?
  • 我可以使用 sed,但不能使用 perl。我基本上不允许使用项目中每个人都可以使用的东西。 sed、awk、bash 都差不多。

标签: regex bash


【解决方案1】:
regex='([0-9]+)\.[^.]*$'
[[ $file =~ $regex ]] && number=${BASH_REMATCH[1]}

这使用了 bash 被低估的 =~ 正则表达式运算符,它将匹配项存储在名为 BASH_REMATCH 的数组中。

【讨论】:

    【解决方案2】:

    您可以使用参数替换来做到这一点

    var=kej10_sdlkei450_sdlekr_310.txt
    var=${var%.*}
    var=${var##*_}
    echo $var
    310
    

    【讨论】:

      【解决方案3】:

      使用一系列 Bash Shell 扩展

      虽然不是最优雅的解决方案,但此解决方案使用shell parameter expansions 序列来实现所需的结果,而无需定义特定的扩展。例如,此函数使用长度和偏移扩展来查找删除文件扩展名后的数字:

      extract_digit() {
          local basename=${1%%.*}
          echo "${basename:$(( ${#basename} - 1 ))}"
      }
      

      捕获函数输出

      您可以通过以下方式在变量中捕获输出:

      $ foo=$(extract_digit sdflkej10_sdlkei450_sdlekr_1.txt)
      $ echo $foo
      1
      

      函数的示例输出

      $ extract_digit sdflkej10_sdlkei450_sdlekr_1.txt
      1
      
      $ extract_digit sdflkej10_sdlkei450_sdlekr_9.txt
      9
      
      $ extract_digit sdflkej10_sdlkei450_sdlekr_10.txt
      0
      

      【讨论】:

        【解决方案4】:

        这应该照顾你的情况:

        INPUT="some6random7numbers_12345_moreletters_789.txt"
        SUBSTRING=`expr match "$INPUT" '.*_\([[:digit:]]*\)'`
        echo $SUBSTRING
        

        这将输出789

        【讨论】:

          【解决方案5】:

          这里不需要正则表达式,你可以使用IFS

          var="kej10_sdlkei450_sdlekr_310.txt"
          v=$(IFS=[_.] read -ra arr <<< "$var" && echo "${arr[@]:(-2):1}")
          echo "$v"
          310
          

          【讨论】:

            猜你喜欢
            • 2014-09-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-10-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多