逆参照を使用して、キャプチャグループと呼ばれるBash正規表現を使用しますか?

逆参照を使用して、キャプチャグループと呼ばれるBash正規表現を使用しますか?

私は次のことをしたいと思います -

bash-shell>echo (*).prop ; echo \1 

明らかに上記の方法は機能しません。しかし、これが可能かどうか、それに対応するものが何であるか疑問に思います。

*現在のディレクトリ内のすべてのファイルと一致するようにシェルにワイルドカードを使用したいと思います。もちろん、上記の検索を.propで終わるファイルに限定してください。 .prop拡張子のないファイル名をキャプチャし、逆参照を使用して印刷します。\1

私が追加した例は、説明するのが簡単です。私のユースケースはより複雑ですが、要件を満たすために逆参照が必要です。

答え1

ksh93は、AFAIK、ksh93、およびzshサポートキャプチャグループをサポートする逆参照をサポートする唯一のシェルです。これはここで探しているものと似ていますが、提案したように使用することはできません。 (ksh93 \1)または$match[1](zsh)には、一致するファイルごとにキャプチャされたコンテンツへの参照が必要です。

ksh93では、次のことができます。

files=( ~(N)*.prop )
(( ${#files[@]} == 0 )) || printf '%s\n' "${files[@]/@(*).prop/\1}"

zshから:

set -o extendedglob
files=( *.prop(N) )
print -rC1 -- ${files/(#b)(*).prop/$match[1]}

演算子の一部として、キャプチャグループへの参照が一致する各ファイルに対して実行されます${array/pattern/replacement}

これはzshval glob修飾子の一部として実行することもできますe

set -o extendedglob
print -rC1 -- *.prop(Ne['REPLY=${REPLY/(#b)(*).prop/$match[1]}'])

:r拡張を削除するための専用のootname修飾子があります。

print -rC1 -- *.prop(N:r)

Bashではいつでも次のことができます。

shopt -s nullglob
files=( *.prop )
(( ${#files[@]} == 0 )) ||
  printf '%s\n' "${files[@]%.prop}"

逆参照は、基本正規表現およびその他の正規表現エンジンの機能です。

bash実際には組み込みの正規表現一致演算子がありますが、拡張正規表現(ERE)を使用していることに注意してください。標準EREは逆参照を作成しませんが、一部の実装ではこれを拡張としてサポートしています。

存在する:

[[ aa =~ (.)\1 ]]

\1\1これは標準のERE演算子ではないため、それほど効率的ではありませんが、bashはそれを引用符で扱うことによって1システムの正規表現エンジンを(.)1正規表現として呼び出すためです。

regexp='(.)\1'
[[ aa =~ $regex ]]

GNUシステムなど、拡張正規表現エンジンが逆参照をサポートするシステムで動作します。

これにはあなたが望むものがたくさん含まれています。

成功後

[[ $file =~ ^(.*)\.prop$ ]]

一致するコンテンツは(.*)(配列の2番目の要素、zshでキャプチャされたコンテンツが配列に入る)で使用できるため、次のことができます。${BASH_REMATCH[1]}$BASH_REMATCH$match

shopt -s nullglob
for file in *.prop; do
  if [[ $file =~ ^(.*)\.prop$ ]]; then
    printf '%s\n' "${BASH_REMATCH[1]}"
  fi
done

(たとえば、ファイル名がユーザーのロケール文字セットにエンコードされていない場合、ファイルの失敗が*.prop発生する可能性があります。)[[ $file =~ ^(.*)\.prop$ ]]


とにかく、POSIXシェルでは\1orと同じです。つまり、引用されます。したがって、POSIXと互換性があるように設計されたシェルは、POSIXがそれを指定していない領域(たとえば、ksh93で2つの同じ文字で始まるファイルを探す場合(引用符なしの文字が指定されていない動作を引き起こす場合)、または以前に言及しました。ある場合にのみ異なる意味を与えることができます。ファイルはPOSIX指定演算子ではありません。'1'"1"1print -r -- @(?)\1*()"${files[@]/@(*).prop/\1}"${array/pattern/replacement}

答え2

GNUを使用するbasename(またはFreeBSDまたは複数の単一引数を処理し、各引数からサフィックスを削除する非標準およびbasenameオプション-aを提供する他の実装では):-s

basename -a -s .prop -- *.prop

*.propこれにより、パターンと一致しますが.propファイル名サフィックスが削除されたファイル名が提供されます。

提案したものと同様のものを使用してください。

names=( *.prop )
printf '%s\n' "${names[@]%.prop}"

これにより、一致するすべての名前を含む配列が作成されますnames。その後、使用された変数置換は、各名前を出力する前にprintfファイル名のサフィックスを削除します。.propprintf

配列に で終わる文字列だけが含まれていることがわかっているので、.prop2行目は次のように短縮できます。

printf '%s\n' "${names[@]%.*}"

これにより、配列内の各文字列から最後の点(および点)の後のすべての項目が削除されますnames

シェルは実際にファイル名を一致させるために正規表現を使用しません。これは、ファイル名のグロービングパターンを介して行われます。正規表現は、ファイル内のテキストを一致させるためにより一般的に使用されます。

関連情報