web-dev-qa-db-ja.com

このgrepの何が問題になっていますか?

> output2.txt
cd # some directory i'm trying to search
find views/shared -type f -name "*.js" -print0 | while IFS= read -r -d $'\0' line; do
    echo -n "${line%.js}" | tee -a ~/Documents/counter/output2.txt
    grep -lr "${line%.js}" . | wc -l | tee -a ~/Documents/counter/output2.txt   # produce a count of occurrences
    regex='[a-zA-Z]+.extend'
    grep -f $line $regex
    grep -lr "${line%.js}" . | tee -a ~/Documents/counter/output2.txt           # produce a list of occurrences
done

戻り値

grep: brackets ([ ]) not balanced

私がウェブ上で見たすべての例は、ここには何も問題がないことを示しているように見えるので、私はかなり混乱しています

確かに角かっこはバランスが取れていますね。

1
itsmichaelwang

あなたの問題は-fオプションです。検索するファイルを指定する代わりに、-fはパターンのリストを読み取るファイルを指定します。 OS X grepのmanページで説明されていますが、 あまり明確ではありません

 -f file, --file=file
         Read one or more newline separated patterns from file.  Empty pattern lines match every input
         line.  Newlines are not considered part of a pattern.  If file is empty, nothing is matched.

GNU grepのヘルプは、実際にはもっと簡単です。

$ grep --help | grep -- '-f,'
  -f, --file=FILE           obtain PATTERN from FILE
$ 

-fのこの動作は、GNU grepのマニュアルページによると、specified by POSIX.

あなたの修正はおそらくあなたの行を変更することです:

grep -f $line $regex

に:

egrep "$regex" -- "$line"
  • 拡張正規表現を使用しているため、egrepまたはgrep -Eを使用してください
  • --は、grep$line変数のオプションを解析できないようにします。 「-r funnyname.js」という名前のファイルからユーザーを保護します
1
user4443

Grepパイプに入る入力に角かっこ( '['および ']')が含まれている場合、grepはそれらを適切に処理するのに苦労します。まず、次のようなものを使用して入力を「サニタイズ」し、各角括弧を角括弧のペアで囲みます。これにより、一致するリテラル文字として解釈されます。

CommandYouWantToPipeThroughGREP | sed -e 's^\([][]\)^\[\1\]^g' | grep ...

Sedコマンドの説明:

sed -e:式は-eの後に続きます。一重引用符または二重引用符で囲む必要があります。

s^: [検索する。 「^」はフィールド区切り文字として使用されています。 「^」が表示されるたびに、検索オプションの新しい部分が区切られます。

\(...\)および\1:エスケープされた括弧は、sedの変数としてアクセスできるようにするパターンを囲みます。最初のそのようなパターンは「\ 1」と呼ばれます。 2番目は「\ 2」などです。

[][]:外側の2つのブラケットが内側の2つを囲んでいます。 「[」の後の最初の文字は、自動的にリテラルであると見なされます(エスケープ/特別な意味はありません)。その最初の文字は角かっこであるため、「^」で区切られたフィールドの終わりの前の唯一の角かっこでない限り、次の角かっこもリテラルであると見なされます。 (少なくとも、それがどのように機能するかについての私の理解です...)

\[\1\]:sed変数1( "\ 1")をリテラル括弧で囲み、出力に送信します。

g:[g] reedy。これは、「最初の例だけでなく、検索テキストのすべての例を見つけて置き換える」という意味です。

したがって、grepを介してパイプする前に、このsedコマンドを介して角括弧を含む可能性のある入力をパイプするだけで、grepは角かっこを特殊文字として解釈するのではなく、文字通り検索します。残念ながら、別のgrepコマンドにパイプする場合は、最初のコマンドの後で、ブラケットを再度エスケープするために、もう一度sedを実行する必要があるようです。

0
DaneM