Grep unter macOS: Finden Sie eindeutige Vorkommen einer Erfassungsgruppe im regulären Ausdruck

481
Dan Burzo

Ich bin auf macOS und möchte mit grep(oder einem ähnlichen Tool) eindeutige Vorkommen eines bestimmten Musters in einer Codebase finden. Für das Finden aller console.somemethod()Aufrufe in JavaScript habe ich beispielsweise Folgendes entwickelt:

grep -oiER "console\.([a-z]+)\(" . | sort -u 

Aber das bringt mir Ergebnisse in der Form:

./tools/svg-inject/node_modules/with/node_modules/acorn/src/bin/acorn.js:console.log( ./tools/svg-inject/node_modules/wordwrap/README.markdown:console.log( ./tools/svg-inject/node_modules/wordwrap/example/center.js:console.log( ./tools/svg-inject/node_modules/wordwrap/example/meat.js:console.log( ./tools/svg-inject/node_modules/yargs/README.md:console.dir( ./tools/svg-inject/node_modules/yargs/README.md:console.log( ./tools/svg-inject/node_modules/yargs/index.js:console.log( ./tools/svg-inject/node_modules/yargs/lib/usage.js:console.error( ./tools/svg-inject/node_modules/yargs/lib/usage.js:console.log( ./webpack.config.js:console.info( Console.sendTo( console.error( console.log( console.markTimeline( console.reactStackEnd( console.timeEnd( console.trace( console.warn( 

Ich möchte es auf einzigartige Spiele der beschränken ([a-z]+)Gruppe nur :

info sendTo error log markTimeline reactStackEnd timeEnd trace warn 

Entschuldigung, wenn ich eine alte Frage wieder aufhitze!

2
Was ist Ihr erwartetes Ergebnis? Toto vor 6 Jahren 0
Hoppla, das erwartete Ergebnis wurde der Frage hinzugefügt. Dan Burzo vor 6 Jahren 0
Normalerweise würde ich für diese Art `sed 'verwenden, aber es funktioniert nur mit einer bestimmten Dateiliste (keine` -R`-Option). Sie können die vorhandene "grep" -Ausgabe durch "sed" weiterleiten, aber dies bietet keinen Vorteil gegenüber dem Durchleiten von "perl" oder einem zweiten "grep", wie in @ Totos Antwort. Wenn Sie die Tiefe des Verzeichnisbaums kennen, können Sie `sed -n 's /^.* console \. \ ([Az] + \) (. * $ / \ 1 / p' * * / * * / verwenden. * / * * / * / * / * | sort -u` (für drei Unterverzeichnisebenen). Es lohnt sich, `sed` kennenzulernen, und [this] (http://www.grymoire.com/unix/sed) .html) ist eine gute Einführung. AFH vor 6 Jahren 1

1 Antwort auf die Frage

2
Toto

Verwenden Sie die -POption für Perl Regex mit \KDirektive in der Regex, die den vorherigen String-Part-Match aus dem Ergebnis ausschließt:

grep -ioP "console\.\K[a-z]+" file.txt log log log log dir log log error log info sendTo error log markTimeline reactStackEnd timeEnd trace warn 

Ich habe Ihre Beispielzeilen in file.txt zum Testen abgelegt.

So beschränken Sie sich auf ein eindeutiges Vorkommen:

grep -ioP "console\.\K[a-z]+" file.txt | sort -u dir error info log markTimeline reactStackEnd sendTo timeEnd trace warn 

Eine andere Lösungsoption -P wurde die macOS-Version entfernt10.8

Wenn Sie Perl installiert haben:

perl -nle 'print $1 if /console\.([a-z]+)/' file.txt | sort -u dir error info log mark react time trace warn 

Um mit allen Dateien im Verzeichnis zu arbeiten:

perl -nle 'print $1 if /console\.([a-z]+)/' * | sort -u 
Oof, ich habe vergessen zu erwähnen, dass ich auf macOS bin und der Befehl scheint nicht zu funktionieren (möglicherweise fehlt das `-P`-Flag). Dan Burzo vor 6 Jahren 0
@ Dan: Siehe meine Bearbeitung, es sollte funktionieren, wenn Sie Perl installiert haben Toto vor 6 Jahren 1
Aah, fast da! Gibt es eine Chance, dass es im aktuellen Ordner rekursiv funktioniert, um alle Dateien abzugleichen? Dan Burzo vor 6 Jahren 0
Dies ist die letzte, herrliche Form: `find. -exec perl -nle 'print $ 1 wenn /console\.([az(++)\(/i' {} + | sort -u` Dan Burzo vor 6 Jahren 0
@ Dan: Ändern Sie `file.txt` natürlich in` * ` Toto vor 6 Jahren 0
(Ich hatte es mit `./**/*. Js` versucht, aber ich habe den Fehler 'Argumentliste zu lang` bekommen.) Dan Burzo vor 6 Jahren 0
@Dan: Gern geschehen, froh, dass es hilft. Toto vor 6 Jahren 0