「*」ワイルドカードに一致するファイル名のサブストリングをどのように取得しますか?

「*」ワイルドカードに一致するファイル名のサブストリングをどのように取得しますか?

次のファイルを含むディレクトリがあるとします。

touch doc-mike.txt doc-jane.txt doc-susan.txt

次の構造を使用して、スクリプト内のこれらのファイルに対して特定のタスクを実行できます。

for fname in doc-*.txt; do
    echo input: ${fname}
done

ただし、ワイルドカードに一致するファイル名の部分文字列を取得するには、いくつかの難しいプロセスが必要です。

for fname in doc-*.txt; do
    wildcard=${fname#doc-}
    wildcard=${wildcard%.txt}

    echo input: ${fname} output: output-${wildcard}.results
done

これは働きます:

input: doc-jane.txt output: output-jane.results
input: doc-mike.txt output: output-mike.results
input: doc-susan.txt output: output-susan.results

"*"しかし、globワイルドカードと一致する部分文字列を取得するためのより良い/簡単な方法が必要だと思います。

答え1

私が考えることができる最も近いのは、BASH_REMATCHbashが正規表現リテラルの結果をその変数に格納するためです。

$ for fname in doc-*.txt; do 
    [[ $fname =~ doc-(.*).txt ]];
    echo "input: ${fname} output: output-${BASH_REMATCH[1]}.results";
done
input: doc-jane.txt output: output-jane.results
input: doc-mike.txt output: output-mike.results
input: doc-susan.txt output: output-susan.results

(.*)正規表現の最初のグループと同様にBASH_REMATCH[1]

答え2

zsh混ぜることができます。glob修飾子、履歴拡張修飾子、globbingフラグ行ってください。
以下で、拡張ワイルドカードと記録パターンの交換モードを有効にしたとします。

setopt extendedglob
setopt histsubstpattern

だからあなたは実行することができます

print doc-*.txt(#q:s/(#b)doc-(*).txt/'${match[1]}'/)

これは出力されます

jane mike susan

通常どおり、これを通常のファイルのみを選択したり、単語の先頭/末尾に式を固定するなど、他の修飾子/修飾子/フラグと組み合わせることができます。


ただし、各ファイル名を繰り返す場合は、zshパラメータ拡張をネストしてコードを次のように単純化できます。

for fname in doc-*.txt; do
    print input: ${fname} output: output-${${fname#doc-}%.txt}.results
done

上記(返信:あなたのコメント)は単一の式を使用し、中間変数は必要ありません。

答え3

また試すことができます

for fname in doc-*.txt; do 
  echo "input: ${fname} output: output-${fname:4:$((${#fname}-8))}.results"
done

関連情報