grepは、ターミナルコマンドラインとbashスクリプトで異なる結果を表します。

grepは、ターミナルコマンドラインとbashスクリプトで異なる結果を表します。

grepを使用して特定の拡張子と特定のディレクトリにあるファイルをフィルタリングするbashスクリプトがあります。スクリプトは次のとおりです。

generate_exclud_extensions() {
  echo "\"(cpp$"
}

generate_exclude_dirs() {
  echo "|^test)\""
}

command=$(generate_exclud_extensions)$(generate_exclude_dir)
echo $command
git ls-files | grep -vE $command

スクリプトは、cpp拡張子を持つファイルとtestディレクトリの下のファイルをフィルタリングする必要があります。しかし、結果は最初の項目だけをフィルタリングし、2番目の項目は残しました。

事実 1:echo $command出力"(cpp$|^test)"し、端末で完全なコマンドを実行すると、git ls-files | grep -vE ""(cpp$|^test)""正しい結果が得られました。

事実2:grepを次のように2回試しました。

git ls-files | grep -vE "cpp$" | grep -vE "^test"

Bashスクリプトでも同じエラーが発生しますが、端末で修正されました。

探していましたが、まだ運がありませんでした。誰もがこれについて明らかにすることができれば幸いです。

答え1

問題を再現できました。これは2つの機能のbashエスケープの問題です。この試み:

generate_exclude_extensions() {
  echo '(cpp$'
}

generate_exclude_dirs() {
  echo '|^test)'
}

command=$(generate_exclude_extensions)$(generate_exclude_dirs)
echo "$command"
git ls-files | grep -vEe "$command"

再現したいコード

generate_exclude_extensions() {
  echo '(cpp$'
}

generate_exclude_dirs() {
  echo '|^test)'
}

command=$(generate_exclude_extensions)$(generate_exclude_dirs)
echo "$command"
echo -e 'cpp\n
test\n
test456\n
display?5\n' | grep -vEe "$command"

スクリプトに2つのタイプミスがあります

generate_exclude_dir -> generate_exclude_dirs
generate_exclud_extensions -> generate_exclude_extensions

:) 楽しくお過ごしください

答え2

別のアプローチは次のとおりです。

generate_exclude_extensions() {
  echo 'cpp$'
}

generate_exclude_dirs() {
  echo '^test'
}

exclusions=$(
  generate_exclude_extensions
  generate_exclude_dir
)

printf '%s\n' "$exclusions"

git ls-files | grep -ve "$exclusions"

つまり、1行に1つの除外項目がある場合-E

答え3

Gitを使用できますexclude パス指定フィルタ出力:

exclude_extensions=( '*cpp' '*.txt' ) # added `*.txt` as sample file extension
exclude_dirs=( 'test/*' )             # exclude files in relative directory `test`

git ls-files "${exclude_extensions[@]/#/:(exclude)}" "${exclude_dirs[@]/#/:(exclude)}"

パラメータ拡張は、"${exclude_...[@]/#/:(exclude)}"接頭辞付きの空白で区切られた項目の配列と、その後にパス指定:("magic word"が続く配列に拡張されます。exclude)

結果のコマンドは次のとおりです。

git ls-files ':(exclude)*cpp' ':(exclude)*.txt' ':(exclude)test/*'

関連情報