Bash

辨識可變長度文件名的合適正則表達式是什麼?

  • November 19, 2020

我有一個 bash 腳本,可以從遠端伺服器分類和檢索文件。我對基於文件名的分類步驟有疑問。

我能夠正確辨識由文件名開頭定義的不同文件系列。文件名可以是:

ala-olo_ulu-1602915797.txt
ala-olo_ulu-1602915799.txt
ili-olo-1602915897.txt
ili-olo-1602915997.txt
ili-olo-pip-1602925797.txt
ili-olo-pip-1602935797.txt

在這個例子中,我有 3 個家庭:( ala-olo_ulu ili-olo ili-olo-pip 純例子:))

在循環的一次迭代中處理每個族。在這樣的迭代中,我在變數中提供了姓氏BASE_NAME(例如ili-olo)。

我的麻煩是在將文件同步到本地之前的去皮步驟。我正在使用以下 ssh 命令對其進行管理。

     ssh root@"${RMT_IP}" '
         for FILE in "'${BASE_NAME}'*'${FILE_EXTENSION}'"; do
           tar -rf "'${BASE_NAME}'.tar" ${FILE} --remove-files
         done' < /dev/null

不幸的是,使用此腳本,如果ili-olo在之前管理過ili-olo-pip,則存檔將包含兩個系列(它們都共享相同的開始)。然後何時ili-olo-pip管理,它們將不再是任何文件,並且 tar 命令以錯誤結束。(這就是我發現問題的方式)。

我想,我寧願使用正則表達式來指定文件名的變數部分是數字部分。請問,如何更改for循環定義,以使以相同字元串開頭的家庭不會進入相同的焦油?

for FILE in "'${BASE_NAME}'*'${FILE_EXTENSION}'"; do

?

例如,數字部分始終具有相同的位數(它是時間戳,具有秒精度)1602915797

我感謝你的幫助。祝你有美好的一天,Bests,皮埃爾

如果您可以zsh同時用作本地和遠端 shell,那就更容易了:

ssh root@$RMT_IP zsh << EOF
 set -o extendedglob # for (#c10)

 for file in ${(qq)BASE_NAME}-[0-9](#c10).${(qq)FILE_EXTENSION}(N); do
   tar -rf ${(qq)BASE_NAME}.tar \$file --remove-files
 done
EOF

[0-9](#c10)匹配 10 個十進制數字的序列。另請參閱[0-9]##[0-9](#c1,)一個或多個數字相同或<100000-9999999999>(不需要extendedglob)組成該範圍內的數字的十進制數字序列。

sshd在伺服器上執行使用者的登錄 shell 來解釋作為參數傳遞的程式碼。由於我們不知道它是什麼(通常是root,那隻是sh),我們只是編寫該程式碼zsh,以啟動一個zshshell 並zsh在標準輸入上傳遞程式碼。

使用這樣的 here-document 可以更輕鬆地建構要由那裡的遠端 shell 解釋的 shell 程式碼。由於EOF沒有引用,本地 shell 將在本地執行擴展。

重要的是要跟踪哪些擴展是要在本地完成的,哪些是要由遠端 shell 完成的。

上面${(qq)BASE_NAME}是由本地shell擴展的,我們使用(qq)參數擴展標誌將結果用單引號括起來,這樣遠端shell就將其作為文字字元串。

$file必須由遠端 shell 擴展,因此我們在它前面加上前綴,\以便將文字$file傳遞給遠端 shell。

如果zsh在遠端機器上不可用,但bash可以,您可以這樣做(仍在zsh本地使用):

ssh root@$RMT_IP bash --norc << EOF
 shopt -s extglob nullglob # for +(...)
 export LC_ALL=C

 for file in ${(qq)BASE_NAME}-+([0-9]).${(qq)FILE_EXTENSION}; do
   tar -rf ${(qq)BASE_NAME}.tar "\$file" --remove-files
 done
EOF

bash沒有zsh’s x(#c10)glob 運算符的等價物,但有了extglob,它支持 ksh 的子集({10}(x)雖然不幸的是這裡不是),包括+(x)匹配一個或多個x. 所以這+([0-9])將匹配一個或多個數字,而不僅僅是 10。

要匹配 10 位數字,您仍然可以執行[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].

引用自:https://unix.stackexchange.com/questions/620445