構成を変更すると、サフィックスが.originalのソースファイルのコピーが作成されます。これで、すべての* .originalファイルを見つけて、.originalサフィックスがある場合とない場合の両方のバージョンを使用する単純なスクリプトを作成しています。
パスの中央にある文字列とlocate
ファイルが一致しないことを避けるために、正規表現でコマンドを使用しました。original
私のコマンドはlocate --regex ^.*\\.original$
完全に実行されていますin terminal
。 .original サフィックスで終わるすべてのファイルを探します。file.original
しかし、in bash script
で同じコマンドを使用すると、次のバリアントがfor loop
返されます。file.original
file-original
file_original
.originalファイルのみを取得するには、正規表現またはforループをどのように変更する必要がありますか?
私の殻は次のとおりです
$ echo $BASH
/usr/bin/bash
私のbashスクリプトは次のとおりです
#!/usr/bin/bash
echo "Plain locate command:"
locate --regex ^.*\\.original$ | grep test
echo "For loop:"
for file in `locate --regex ^.*\\.original$ | grep test`; do
echo $file
done
テストに使用できます。
mkdir /tmp/test
touch /tmp/test/file.original
touch /tmp/test/file-original
touch /tmp/test/file_original
updatedb
locate --regex ^.*\\.original$
私のターミナルで次を探します。
/tmp/test/file.original
しかし、私のスクリプトでは以下を探します。
Plain locate command:
/tmp/test/file.original
For loop:
/tmp/test/file-original
/tmp/test/file.original
/tmp/test/file_original
答え1
バックティックにはより多くのエスケープが必要です。これがあなたがそれを好むべき理由の1つです$()
(この答えの「バックスラッシュの楽しみ」を参照:$(stuff)
これらとそしての違いは何ですか`stuff`
?)。
バックティック内でエスケープ処理が不十分なため、文字列が最終的に正規表現として解釈されたときにエスケープしたい点はエスケープされません。
関連する行を次のように変更します。
for file in $(locate --regex '^.*\.original$' | grep test); do
メモ:
バックスラッシュを便利に処理するために単一引用符を使用します。そしてアスタリスク。元のコードでは、引用符がなくエスケープされていないアスタリスクをトリガーできます。ファイル名拡張子。
^.*
正規表現には何も変更されませんでした。一重引用符で\.original$
十分です。^.*
ファイル名拡張の可能性を指摘するためにそのまま維持することにしました。に慣れる参照変数(例えば
echo "$file"
)。リンクされた答えも引用を提案しますが、これは$()
ループfor
では間違っています。引用しないのも$()
間違いです。どちらも間違っていたから…一般的に言えば
for
このようなループを作成するのは一般的に間違いです。。これはBashの最初のトラップ。より良い出力でlocate
操作を実行するには、xargs
nullで終わる文字列として扱うのが最善です。locate -0 … | grep -z … | xargs -r0 …
これらのオプションは移植可能ではありません。