grep -r (rekursiv), alle Verzeichnisse entfernen/ausblenden

grep -r (rekursiv), alle Verzeichnisse entfernen/ausblenden

grep -r asdfNeuling hier - ich möchte jedoch laufen ,Ich möchte nur eindeutige Übereinstimmungen in meinen Verzeichnissen(d. h. alle Verzeichnisse werden ignoriert, es werden nur eindeutige Übereinstimmungen angezeigt).

Also habe ich ausgeführt grep -r asdf | sort --unique. Dies funktioniert jedoch nicht, da die Verzeichnisnamen unterschiedlich sind ( dir1/a.txt asdfund dir2/a.txt asdf).

Ich habe keine Option grep -riolzum Ausschließen von Verzeichnissen gesehen (ich habe es z. B. versucht) und ich denke, das ergibt für den Umfang der Funktion kaum Sinn. Kann ich die Verzeichnisse irgendwie ausschneiden und nur den übereinstimmenden Dateinamen + Übereinstimmung anzeigen (möglicherweise ohne einen bewusstseinsverändernden/universumsverändernden regulären Ausdruck/sed/...)?

Antwort1

Ich denke, dass dies mit den Standardfunktionen grepnicht möglich ist.

Sie könnten etwas wie das Folgende verwenden, das nur ein „kleiner“ regulärer Ausdruck ist:

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

Hinweis: Dieser Ansatz funktioniert nicht, wenn das Suchmuster ein/

Antwort2

Versuche dies,

grep -r abcd | awk -F ':' '{gsub(/.*\//,"",$1) }1' | awk '!seen[$1]++'
  • gsubentfernt die Verzeichnisstruktur. (/.*\//,"",$1)entfernt("") alles(.*) vor der letzten Übereinstimmung von '/' im ersten Feld($1).
  • !seen[$1]++verleiht dem Dateinamen eine Eindeutigkeit.

Hinweis: Der Verzeichnisname darf nicht enthalten sein :.

Antwort3

Dies gruppiert nach Basisnamen und Grep-Ausgabe:

   ]# 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

Früher habe ich grep -oeinige Duplikate erhalten. Gleichzeitig fehlen die Schrägstriche ...

Wenn die Namen enthalten, :funktioniert das sed nicht richtig. Der reguläre Ausdruck wirft zuerst alles bis zum letzten weg /und speichert dann alles bis zu einem :als \1.

Ich habe „ -Ewegen des (Unterausdrucks)“ und „ |wegen des Schrägstrichs“ verwendet.


Der Unterausdruck (.*:)ist etwas einfach (schlägt fehl, wenn eine grepped-Zeile einen Doppelpunkt enthält). Wenn Sie den Doppelpunkt weglassen, schlägt der Ausdruck fehl, wenn die Zeile einen Schrägstrich enthält.


Wenn ich mir diese Ausgabe anschaue, sage ichdas ist unmöglichtheoretisch (um die Ausgabe von grep auf diese Weise zu analysieren):

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

Dies ist identisch.Ich brauchte ein Verzeichnis mit einem Doppelpunkt am Ende und eine Datei mit überlappendem Namen und Inhalt.

]# ls d* 
d

'd:':
ir

grep --colormacht den Unterschied!


Das includeVerzeichnis ist das aus dem Linux-Kernel-Quellcode. Eine vollständige Zeile in einer Include-Datei sieht folgendermaßen aus.

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

Antwort4

Mit der Ausgabe von sollte grep --nulldas folgende GNU- awkProgramm mit jedem Dateinamen funktionieren:

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

verwandte Informationen