如何获取文件路径中间的 6 位数字

如何获取文件路径中间的 6 位数字

我有一个像这样的文件路径名

/dbfs/mnt/dlg2stage/foldername/backupname/201906_load_1_20210623-151602.tar.tgz

我试图只获取六位数字201906 并打印它们。我尝试过sedawk失败了。

答案1

假设这些是您系统上的实际文件,您可以使用 shell 循环轻松提取目录中_匹配的每个文件的文件名中第一个之前的部分:*_*.tar.tgz/dbfs/mnt/dlg2stage/foldername/backupname

for pathname in /dbfs/mnt/dlg2stage/foldername/backupname/*_*.tar.tgz; do
    name=$( basename "$pathname" )
    printf '%s\n' "${name%%_*}"
done

basename实用程序将为您提供路径名的文件名部分。鉴于您显示的示例,这会将字符串分配201906_load_1_20210623-151602.tar.tgz给变量name。您也可以用来name=${pathname##*/}做同样的事情(这个参数扩展删除了字符串的初始部分$pathname,直到并包括最后一个/)。

参数扩展${name%%_*}将导致_*从 value 中删除最长的尾随子字符串匹配$name。在所示示例中,这将删除第一个_字符及其右侧的所有内容,留下子字符串201906,然后使用 打印该子字符串printf

答案2

zsh

file=/dbfs/mnt/dlg2stage/foldername/backupname/201906_load_1_20210623-151602.tar.tgz
set -o extendedglob # for (#c6)

first_6_digits_of_file_tail=${(M)${file:t}[0-9](#c6)}

哪里${file:t}需要尾巴文件的名称(其基本名称),返回匹配模式${(M)var#pattern}的开头部分。$varM

POSIXly,您可以使用:

first_6_digits_of_file_tail=$(
  LC_ALL=C expr "/$file" : '.*/\([0-9]\{6\}\)[^/]*/*$'
)

LC_ALL=C忽略用户的区域设置并将所有字节视为字符(大多数系统上按照 ASCII 的第 128 位,包括 / 和 0123456789 数字),以便.保证[^/]匹配字节并且[0-9]仅包括 0123456789。它不是zsh范围基于的数字codepoints 和 zsh 认为每个字节不以其他方式形成有效字符的一部分,就好像它是一个字符一样。

前置/以避免以$file运算符开头-或看起来像expr运算符的值出现问题,并保证字符串至少包含/正则表达式所期望的一个。

我们不允许最后的 except/之后的 s获得与使用or zsh 的解决方案相同的行为,其中or的基本名称是。/XXXXXXbasename$file:t/foo/bar//foo/bar////bar

请注意,如果没有匹配项,而且该 6 位数字序列代表 0 数字(如 中所示/path/to/000000_whatever),它会返回 false/失败退出状态。

答案3

我想你只是想打印201906给定的路径字符串。在该示例中,这六位数字是:前面有斜杠的前六位数字

我将路径放入变量中只是为了使命令更易于阅读:

% path_str='/dbfs/mnt/dlg2stage/foldername/backupname/201906_load_1_20210623-151602.tar.tgz'

% echo $path_str | sed 's/.*\/\([0-9]\{6\}\).*/\1/'
201906

这是我如何建立匹配和替换的sed:

  • \/[0-9]\{6\}: 匹配斜杠和 6 位数字
  • \/\([0-9]\{6\}\): 是一样的,但现在在捕获组或者子表达式(斜杠不在捕获组中)
  • .*\/\([0-9]\{6\}\).*: 匹配之前和之后的所有内容,所以...整条线
  • \1:整行匹配,使用参考第一的(且唯一)捕获组仅用前 6 位数字替换整行

相关内容