
我有一個像這樣的檔案路徑名
/dbfs/mnt/dlg2stage/foldername/backupname/201906_load_1_20210623-151602.tar.tgz
我試圖只獲取六位數字201906
並列印它們。我嘗試過sed
但awk
失敗了。
答案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}
的開頭部分。$var
M
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
zsh 認為每個位元組不以其他方式形成有效字元的一部分,就好像它是一個字元一樣。
前置/
以避免以$file
運算子開頭-
或看起來像expr
運算子的值出現問題,並保證字串至少包含/
正規表示式所期望的一個。
我們不允許最後的 except/
之後的 s獲得與使用or zsh 的解決方案相同的行為,其中or的基本名稱是。/XXXXXX
basename
$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 位數字替換整行