Tips en Trucs 2013

Geavanceerd zoeken met grep

De UNIX grep opdracht zoekt naar tekstfragmenten in bestanden. De find opdracht daarentegen zoekt naar bestanden met een bepaalde naam of eigenschappen. Vandaag publiceer ik wat tips om met grep sneller en efficiënter bestanden te doorzoeken.

Eerst een paar opmerkingen over grep:

Zoals met veel UNIX opdrachten, kan wegens de voorgeschiedenis en compatibiliteit met vorige versies, grep deze extra mogelijkheden maar gebruiken door het opgeven van extra opties.

Versies

GNU grep (standaard aanwezig in de meeste Linux distributies) ondersteunt veel opties, zoals kleuren. BSD grep (aanwezig in op BSD gebaseerde besturingssystemen zoals OSX) ondersteunt minder opties. De systemen zonder GNU grep kunnen steeds GNU grep installeren, GNU grep is namelijk voor alle systemen beschikbaar.

Verschillende bestanden doorzoeken

Het volgende voorbeeld doorzoekt hoofdletter ongevoelig (i), recursief (-R) in de opgegeven map en onderliggende mappen naar de tekst <title> in (--include) HTML bestanden:

grep -Ri --include="*.html" '<title>' ~/Documents/SNT/Linux/Web

Kleuren

Grep kan in de uitvoer zaken zoals bestandsnamen, regelnummers, gezochte tekst en omringende tekst accentueren met kleuren. Deze opties kan je best opslaan in omgevingsvariabelen:

GREP_OPTIONS="--color=always"
GREP_COLORS="ms=01;37:mc=01;37:sl=:cx=01;30:fn=35:ln=32:bn=32:se=36"

En testen door deze voor een grep opdracht te plaatsen:

GREP_OPTIONS="--color=always" GREP_COLORS="ms=01;37:mc=01;37:sl=:cx=01;30:fn=35:ln=32:bn=32:se=36" grep -Ri --include="*.html" '<title>' ~/Documents/SNT/Linux/Web

Opmerking: gebruik GREP_COLORS, en niet de afgeschreven omgevingsvariabele GREP_COLOR. De eerste omgevingsvariabele heeft ook veel meer mogelijkheden.

ASCII zoeken

Standaard decodeert grep de tekstbestanden. Dit vraagt tijd. Als je platte ASCII teksten, zoals broncode van programmeertalen doorzoekt, kun je veel tijd sparen door het decoderen uit te schakelen. Dit doe je door de omgevingsvariabele LC_CTYPE tijdelijk aan te passen naar POSIX.

LC_CTYPE=POSIX grep ...

Regels in de nabijheid weergeven

Met de opties --before-context en --after-context kan je de regels voor en na de zoektekst weergeven. Bij broncode zorgt de optie --line-number voor het nummeren van de weergegeven regels.

grep

Alles in één script

# Search ASCII-string from multiple files in the currect working directory
# E.g.
# search "foobar" "*.html"
# search "foobar" "*.html" myfolder
# By default we excluse dotted files and directoves (.git, .svn)
if [[ ! -n "$1" ]] ; then
	echo "Usage: search \"pattern\" \"*.filemask\" \"path\""
	return
fi

# Did we get path arg
if [[ ! -n "$3" ]] ;
then
	search_path="."
else
	search_path="$3"
fi

# LC_CTYPE="posix" 20x increases performance for ASCII search
# https://twitter.com/jlaurila/status/86750682094374912

# We use specially tuned GREP colors - make sure you have GNU grep on OSX
# https://github.com/miohtama/ztanesh/blob/master/README.rst

GREP_COLORS="ms=01;37:mc=01;37:sl=:cx=01;30:fn=35:ln=32:bn=32:se=36" LC_CTYPE=POSIX \
grep -Ri "$1" --line-number --before-context=3 --after-context=3 --color=always --include="$2" --exclude=".*" "$search_path"/*