可変長ファイル名を識別するのに適した正規表現は何ですか?

可変長ファイル名を識別するのに適した正規表現は何ですか?

リモートサーバー上のファイルを分類して検索する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 (純粋な例:))

各家族はループの1回の反復として扱われます。これらの反復では、変数で使用できる家族名がありますBASE_NAME(例ili-olo:)。

私の問題は、ファイルをローカルにrsync'ingする前に、次の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アーカイブに2つのシリーズ(両方とも同じ起動を共有します)が含まれます。管理されると、ili-olo-pipこれ以上ファイルではなく、tarコマンドはエラーで終了します。 (これが私が問題を見つけた方法です)。

私は、ファイル名の変数部分が数値部分であることを指定するために正規表現を使用する必要があると思いました。for同じ文字列で始まるシリーズが同じtarに入らないように、ループ定義をどのように変更できますか?

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

たとえば、数値部分は常に同じ桁数を持ちます(秒単位のタイムスタンプです)。1602915797

ご協力ありがとうございます。良い一日をお過ごしください、ベスト、ピエール

答え1

ローカルシェルとリモートシェルの両方で利用可能であれば、はるかにzsh簡単です。

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]##1つ以上の数字、または(必ずしもそうではありません)、同じ10進数のシーケンスで構成される範囲の数字を参照してください。[0-9](#c1,)<100000-9999999999>extendedglob

sshdサーバーでユーザーのログインシェルを実行して、引数として渡されたコードを解釈します。私たちはそれが何であるかわからないので(通常root)シェルを起動し、標準入力にコードを渡すためにshこのコードを作成します。zshzshzsh

このようなドキュメントを使用すると、リモートシェルで解釈されるシェルコードをより簡単に構成できます。引用されていないため、EOFローカルシェルはローカルで拡張を実行します。

ローカルで実行する必要がある拡張機能とリモートシェルで実行する必要がある拡張子を追跡することが重要です。

上記は${(qq)BASE_NAME}ローカルシェルによって拡張されます。(qq)パラメータ拡張フラグを使用して結果を一重引用符で囲み、リモートシェルがそれをリテラル文字列として扱うようにします。

$fileリモートシェルで拡張する必要があるため、リテラルをリモートシェルに渡す\ためにプレフィックスを付けます。$file

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

bashzshglob演算子と同等のものはありませんが、x(#c10)使用されると、1つ以上の一致を含むkshのサブセット(残念ながらここにはありません)extglobをサポートします。これは10以外の1つ以上の数字と一致します。{10}(x)+(x)x+([0-9])

10桁の数字を一致させるには、これを実行できます[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]

関連情報