如何取得檔案路徑中間的 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。zshzsh 認為每個位元組不以其他方式形成有效字元的一部分,就好像它是一個字元一樣。

前置/以避免以$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 位數字替換整行

相關內容