grep -r (再帰)、すべてのディレクトリを削除/非表示にする

grep -r (再帰)、すべてのディレクトリを削除/非表示にする

初心者です。走りたいのですgrep -r asdfが、ディレクトリ内で一意の一致のみが欲しい(つまり、ディレクトリを無視して、一意の一致のみを表示します)。

そこで を実行しましたgrep -r asdf | sort --unique。ただし、ディレクトリ名が異なる (dir1/a.txt asdfdir2/a.txt asdf) ため、これは機能しません。

ディレクトリを除外するオプション (たとえば を試しました) が見つかりませんgrep -riolでした。関数のスコープではほとんど意味がないと思います。ディレクトリを切り取って、一致したファイル名と一致のみを表示することはできますか (おそらく、精神/宇宙を曲げる正規表現/sed/... なしで)?

答え1

デフォルトの機能ではgrepこれを実行する方法はないと思います。

次のような「小さな」正規表現を使用することもできます。

grep -r asdf | sed '#^.*/##' | sort --unique

注: この方法は、検索パターンに/

答え2

これを試して、

grep -r abcd | awk -F ':' '{gsub(/.*\//,"",$1) }1' | awk '!seen[$1]++'
  • gsubディレクトリ構造を削除します。 (/.*\//,"",$1)最初のフィールド($1)の最後の '/' の一致の前にあるすべての(.*)を削除します("")。
  • !seen[$1]++ファイル名を一意にします。

注意: ディレクトリ名には:以下が含まれていてはいけません。

答え3

これはベース名と grep 出力でグループ化します:

   ]# grep -ro '#include' include/ |sed -E 's|.*/(.*:)|\1|' |uniq -c |sort|tail -n7
         28 kvm_host.h:#include
         28 mm.h:#include
         29 ib_verbs.h:#include
         31 net_namespace.h:#include
         32 sock.h:#include
         44 fs.h:#include
         48 drmP.h:#include

以前は重複がいくつかありましたgrep -o。同時にスラッシュも省略されます...

名前に が含まれている場合、:sed は正しく動作しません。正規表現は、まず最後の までのすべてを破棄し/、次に までのすべてを として保存し:ます\1

私は-E(部分式) と|スラッシュのために because を使用しました。


部分式(.*:)は少し単純です (grep された行にコロンが含まれている場合は失敗します)。コロンを省略すると、行にスラッシュが含まれている場合に失敗します。


この出力を見て私は言う不可能だよ理論的には(grep の出力をそのように解析するため):

]# grep -r "" d*
d:/ir:/afile...in file "d"
d:/ir:/afile...in file "ir"

これは同一です。最後にコロンが付いたディレクトリと、名前と内容が重複するファイルが必要でした。

]# ls d* 
d

'd:':
ir

grep --color違いを生みます!


ディレクトリincludeは Linux カーネル ソースからのものです。1 つのインクルード ファイル内の 1 行は次のようになります。

]# grep -rH '#incl' include/linux/aio.h 
include/linux/aio.h:#include <linux/aio_abi.h>

答え4

からの出力ではgrep --null、次の GNUawkプログラムは任意のファイル名で動作するはずです。

BEGIN {
    # OFS will be printed between
    # each filename and matched line
        OFS = ":"

    # Use null-byte as a record separator
    # to use with output from grep --null
        RS = "\0"

    # Apart from the first record,
    # everything up to the first newline
    # of a record is the matched line from grep
    # Everything after first newline is a filename
        FPAT = "^[^\n]*|\n.*$"

}
NR == 1 {
    # Entire first record
    # is the first filename
    # set `file` to the basename
        file = gensub(".*/","",1)
        next
}
! seen[file, $1]++ {
    # If filename+match
    # not seen, print it
        print file, $1
}
{
    # Get basename of file
    # from next match
        file = gensub(".*/","",1,$2)
}

grep --null -rF asdf . | awk -f see_above.gawk

関連情報