Neste post Iremos falar sobre o grep, muitos não sabem mas o significado do nome é (Globally Search a Regular Expression and Print), o nome já diz tudo o que esse comando faz, e deixando mais claro a ideia é procurar texto em uma string ou dentro de arquivos e mostrar linhas, ocorrências, usar combinações para pesquisar e o resultado da pesquisa ser mostrado na tela.
Você não precisa se preocupar em instalar o grep, pois ele já esta ae no seu Linux, para confirmar e verificar a versão veja o comando abaixo:
Você não precisa se preocupar em instalar o grep, pois ele já esta ae no seu Linux, para confirmar e verificar a versão veja o comando abaixo:
|
$ grep
Usage: grep [OPTION]... PATTERN [FILE]...
Try ‘grep –help’ for more information.
$ grep –V
grep (GNU grep) 2.16
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by Mike Haertel and others, see <http://git.sv.gnu.org/cgit/grep.git/tree/AUTHORS>.
|
Digitando apenas o comando e dando enter ele não faz nada, porém mostra um exemplo para uso, e com o parâmetro -V a versão atual, no meu caso 2.6.
Agora segue os parâmetros que iremos utilizar e suas funções:
-c | Conta quantas vezes apareceu a string que esta pesquisando |
-v | Mostra na tela “tudo” menos onde houver a ocorrência da string pesquisada |
-i | Realiza uma busca pela string ignorando o case, sendo case-insensitive |
-o | Ira mostrar na tela apenas as ocorrências da string pesquisada ignorando o resto |
-n | Ira mostrar na tela na primeira coluna a linha onde encontrou a string pesquisada |
-B | Numero de linhas a serem impressas antes da linha que contem a string pesquisada [BEFORE] |
-A | Numero de linhas a serem impressas na tela depois da encontrar a linha com a string [AFTER] |
-C | Quantidade de linhas antes e depois da linha que contem a string [CONTEXT] |
-q | Ira procurar pela string informada, porém estará em modo silencioso, nada sera impresso na tela, porém caso encontre o comando encerra com 0, caso não encontre nada será 1 |
-E | Extende o uso de Regex no padrão e combinação, usando logica AND e OR por exemplo |
-f | Um arquivo com combinações de padrões com Regex, podendo usar varias combinações |
-l | Mostra somente o nome do arquivo onde foi encontrado a string pesquisada |
-L | Semelhante ao -v, porque mostra apenas os arquivo que não contem a string informada |
-h | Pesquisa varias arquivos, diretórios se com -r mas não mostra o nome dos arquivos |
-r | Ira realizar uma pesquisa recursiva em todos os diretórios a partir do informado |
–color | Deve-se passar o parâmetro ‘never’ caso não queira que a saída marque com cor a string ou ‘auto’ e ‘always’ para operar conforme necessite. Pode mudar a cor alterando GREP_COLOR, GREP_COLORS no environment |
Exemplo básico
Agora um exemplo básico e bem didático para uso do comando, para isso vou criar um arquivo chamado palavras.txt e inserir um texto dentro e brincar com o grep.
|
echo –ne “amor\ncasa\nCasa\nCASA\nRaspberryPI\nRaspberry PI\nRaspberry B PI\nArduino\narduino\nARDUINO\nIDEArduino\nLinux é o poder\nEu programo Python e você?\n” > palavras.txt
|
Vamos visualizar nosso arquivo palavras.txt.
|
$ cat palavras.txt
amor
casa
Casa
CASA
RaspberryPI
Raspberry PI
Raspberry B PI
Arduino
arduino
ARDUINO
IDEArduino
Linux é o poder
Eu programo Python e você?
|
Agora vamos usar o grep e pesquisar pela string “Raspberry“, podemos usar de duas maneiras com o cat um pipe e logo em seguida um grep ou diretamente com o comando, a primeira opção é muito utilizada, porém você irá perder performance caso realizar pesquisa em muitos arquivo ou em um arquivo longo, veremos ainda neste post sobre isso.
|
$ cat palavras.txt | grep “Raspberry”
RaspberryPI
Raspberry PI
Raspberry B PI
$ grep “Raspberry” palavras.txt
RaspberryPI
Raspberry PI
Raspberry B PI
|
Caso eu queira contar o numero de ocorrências da string “Raspberry”:
|
$ grep –c “Raspberry” palavras.txt
3
|
Se eu quiser ver tudo menos a string que contenham “Raspberry”:
|
$ grep –v “Raspberry” palavras.txt
amor
casa
Casa
CASA
Arduino
arduino
ARDUINO
IDEArduino
Linux é o poder
Eu programo Python e você?
|
Agora quero pesquisar pela string “arduino”.
|
$ grep “arduino” palavras.txt
arduino
|
Temos Arduino escrito de diversas maneiras, então vamos pedir para ser case-insensitive.
|
$ grep –i “arduino” palavras.txt
Arduino
arduino
ARDUINO
IDEArduino
|
E se no lugar de mostrar a linha inteira ou o que estiver junto eu mostrar apenas a string procurada.
|
$ grep –o “arduino” palavras.txt
arduino
$ grep –oi “arduino” palavras.txt
Arduino
arduino
ARDUINO
Arduino
$ grep –oi “Raspberry” palavras.txt
Raspberry
Raspberry
Raspberry
|
Se eu precisar saber o numero da linha onde foi encontrada a string.
|
$ grep –n “Raspberry” palavras.txt
5:RaspberryPI
6:Raspberry PI
7:Raspberry B PI
$ grep –n “duino” palavras.txt
8:Arduino
9:arduino
11:IDEArduino
|
Agora vamos pesquisar pela string “arduino” e obter também as 2 linhas antes da string encontrada.
|
$ grep “arduino” –B 2 palavras.txt
Raspberry B PI
Arduino
arduino
|
O mesmo podemos fazer obtém as linhas depois da linha com a string pesquisada.
|
$ grep “arduino” –A 2 palavras.txt
arduino
ARDUINO
IDEArduino
|
E podemos unir as duas opções, pegando e imprimindo linhas antes e depois da linha que contem a string pesquisada.
|
$ grep “arduino” –C 2 palavras.txt
Raspberry B PI
Arduino
arduino
ARDUINO
IDEArduino
|
Caso não queira mostrar nada na tela, só saber se teve sucesso ou não na pesquisa.
|
$ grep –q “arduino” palavras.txt
$ echo $?
0
$ grep –q “Beaglebone” palavras.txt
$ echo $?
1
|
Apenas reforçando no exemplo acima pesquisei a string “arduino” com o parâmetro -q (modo silencioso) e peguei a saída do ultimo comando executado com (echo $?), logo em seguida pesquisei por “Beaglebone” como não existe a saída foi 1.
Exemplo intermediário
Agora vamos subir um nível e brincar com outros parâmetros. Desta vez vamos criar mais 2 arquivos sistema.txt e hardware.txt, e também copiar a saída do dmesg para dmesg.log e brincar com estes caras.
Preparando os arquivos:
|
$ echo –ne “Linux Ubuntu\nLinux Debian\nLinux Mint\nLinux CentOS\nRaspbian\nYocto RaspberryPI\nBuildroot RaspberryPI\n” > sistema.txt
$ echo –ne “ARM 1176JZF\mARM Cortex-A7\nBCM2835\nBCM2836\nBeaglebone Black\nAM3358\n” > hardware.txt
$ dmesg > dmesg.log
|
Eu criei sistema.txt e hardware.txt com palavras aleatórias, você pode agregar mais palavras para realizar seus testes.
Agora eu quero pesquisar em qualquer arquivo e que contenha a string “Raspberry”.
|
$ grep “Raspberry” *
palavras.txt:RaspberryPI
palavras.txt:Raspberry PI
palavras.txt:Raspberry B PI
sistema.txt:Yocto RaspberryPI
sistema.txt:Buildroot RaspberryPI
$ grep “Raspberry” ./*
./palavras.txt:RaspberryPI
./palavras.txt:Raspberry PI
./palavras.txt:Raspberry B PI
./sistema.txt:Yocto RaspberryPI
./sistema.txt:Buildroot RaspberryPI
|
Os demais parâmetros anteriores se aplicam aqui também.
$ grep –n “Raspberry” *
palavras.txt:5:RaspberryPI
palavras.txt:6:Raspberry PI
palavras.txt:7:Raspberry B PI
sistema.txt:6:Yocto RaspberryPI
sistema.txt:7:Buildroot RaspberryPI
|
Agora se eu criar um diretório exemplo/ e mover o palavras.txt para ele será que vai encontrar a string “Raspberry” nele ainda?
$ mkdir exemplo && mv palavras.txt exemplo/
$ grep “Raspberry” *
grep: exemplo: Is a directory
sistema.txt:Yocto RaspberryPI
sistema.txt:Buildroot RaspberryPI
|
Ele avisa que existe um diretório onde esta sendo feita a pesquisa, para que ele acesse o(s) diretório(s) deve-se passar o parâmetro -r para recursividade.
$ grep –r “Raspberry” *
exemplo/palavras.txt:RaspberryPI
exemplo/palavras.txt:Raspberry PI
exemplo/palavras.txt:Raspberry B PI
sistema.txt:Yocto RaspberryPI
sistema.txt:Buildroot RaspberryPI
|
As vezes só interessa saber a ocorrências mas não o arquivo.
|
$ grep –hr “Raspberry” *
RaspberryPI
Raspberry PI
Raspberry B PI
Yocto RaspberryPI
Buildroot RaspberryPI
|
Se caso queira apenas saber qual arquivo contem a string mas não precisa mostrar ela.
|
$ grep –lr “Raspberry” *
exemplo/palavras.txt
sistema.txt
|
E se quiser saber os arquivos que não possuem a string pesquisada.
|
$ grep –Lr “Raspberry” *
dmesg.log
hardware.txt
|
Habilitando ou não o uso da saída colorida.
$ grep –r —color=always “Raspberry” *
exemplo/palavras.txt:RaspberryPI
exemplo/palavras.txt:Raspberry PI
exemplo/palavras.txt:Raspberry B PI
sistema.txt:Yocto RaspberryPI
sistema.txt:Buildroot RaspberryPI
$ grep –r —color=never “Raspberry” *
exemplo/palavras.txt:RaspberryPI
exemplo/palavras.txt:Raspberry PI
exemplo/palavras.txt:Raspberry B PI
sistema.txt:Yocto RaspberryPI
sistema.txt:Buildroot RaspberryPI
|
Exemplo avançado
Vamos dar mais um passo sobre esse incrível comando, só que agora com o básico de Expressões Regulares, e como exemplo usaremos o dmesg.log gerado acima.
Fazendo uma busca simples pela string “usb”.
$ grep “usb” dmesg.log
[ 0.668550] usbcore: registered new interface driver usbfs
[ 0.668558] usbcore: registered new interface driver hub
[ 0.668582] usbcore: registered new device driver usb
[ 1.996732] usb usb1: New USB device found, idVendor=1d6b, idProduct=0002
[ 1.996735] usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[ 1.996737] usb usb1: Product: EHCI Host Controller
[ 1.996739] usb usb1: Manufacturer: Linux 3.13.0–37–generic ehci_hcd
[ 1.996741] usb usb1: SerialNumber: 0000:00:1d.0
[ 1.997338] usb usb2: New USB device found, idVendor=1d6b, idProduct=0002
[ 1.997340] usb usb2: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[ 1.997342] usb usb2: Product: xHCI Host Controller
[ 1.997344] usb usb2: Manufacturer: Linux 3.13.0–37–generic xhci_hcd
[ 1.997346] usb usb2: SerialNumber: 0000:00:14.0
[ 2.000099] usb usb3: New USB device found, idVendor=1d6b, idProduct=0003
[ 2.000101] usb usb3: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[ 2.000103] usb usb3: Product: xHCI Host Controller
[ 2.000105] usb usb3: Manufacturer: Linux 3.13.0–37–generic xhci_hcd
[ 2.000107] usb usb3: SerialNumber: 0000:00:14.0
[ 2.308561] usb 1–1: new high–speed USB device number 2 using ehci–pci
[ 2.440791] usb 1–1: New USB device found, idVendor=8087, idProduct=8000
[ 2.440794] usb 1–1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[ 2.712387] usb 1–1.5: new full–speed USB device number 3 using ehci–pci
[ 2.805614] usb 1–1.5: New USB device found, idVendor=0cf3, idProduct=0036
[ 2.805616] usb 1–1.5: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[ 2.880293] usb 1–1.7: new high–speed USB device number 4 using ehci–pci
[ 2.972951] usb 1–1.7: New USB device found, idVendor=0bda, idProduct=0129
[ 2.972954] usb 1–1.7: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 2.972956] usb 1–1.7: Product: USB2.0–CRW
[ 2.972958] usb 1–1.7: Manufacturer: Generic
[ 2.972959] usb 1–1.7: SerialNumber: 20100201396000000
[ 3.044205] usb 1–1.8: new high–speed USB device number 5 using ehci–pci
[ 3.201201] usb 1–1.8: New USB device found, idVendor=0c45, idProduct=64af
[ 3.201203] usb 1–1.8: New USB device strings: Mfr=2, Product=1, SerialNumber=0
[ 3.201205] usb 1–1.8: Product: Laptop_Integrated_Webcam_HD
[ 3.201206] usb 1–1.8: Manufacturer: CN0Y3PX8724873AGB17FA01
[ 14.243360] usbcore: registered new interface driver btusb
[ 14.274681] usbcore: registered new interface driver rts5139
[ 14.624063] input: Laptop_Integrated_Webcam_HD as /devices/pci0000:00/0000:00:1d.0/usb1/1–1/1–1.8/1–1.8:1.0/input/input13
[ 14.624169] usbcore: registered new interface driver uvcvideo
[ 14.761434] usbcore: registered new interface driver ath3k
[ 14.781788] usb 1–1.5: USB disconnect, device number 3
[ 14.981529] usb 1–1.5: new full–speed USB device number 6 using ehci–pci
[ 20.075906] usb 1–1.5: New USB device found, idVendor=0cf3, idProduct=0036
[ 20.075911] usb 1–1.5: New USB device strings: Mfr=0, Product=0, SerialNumber=0
|
Bastante coisa não é? Vamos trabalhar em cima extendendo os recursos de Regex da nossa expressão, por exemplo quero somente as linhas que contenham usb2 OU usb3, aplicando a logica OR.
$ grep –E “usb2|usb3” dmesg.log
[ 1.997338] usb usb2: New USB device found, idVendor=1d6b, idProduct=0002
[ 1.997340] usb usb2: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[ 1.997342] usb usb2: Product: xHCI Host Controller
[ 1.997344] usb usb2: Manufacturer: Linux 3.13.0–37–generic xhci_hcd
[ 1.997346] usb usb2: SerialNumber: 0000:00:14.0
[ 2.000099] usb usb3: New USB device found, idVendor=1d6b, idProduct=0003
[ 2.000101] usb usb3: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[ 2.000103] usb usb3: Product: xHCI Host Controller
[ 2.000105] usb usb3: Manufacturer: Linux 3.13.0–37–generic xhci_hcd
[ 2.000107] usb usb3: SerialNumber: 0000:00:14.0
|
Agora, vamos pesquisar por uma linha que contenha “usb” E tambem “Product:”, vamos aplicar a logica AND.
$ grep –E “usb.*Product:” dmesg.log
[ 1.996737] usb usb1: Product: EHCI Host Controller
[ 1.997342] usb usb2: Product: xHCI Host Controller
[ 2.000103] usb usb3: Product: xHCI Host Controller
[ 2.972956] usb 1–1.7: Product: USB2.0–CRW
[ 3.201205] usb 1–1.8: Product: Laptop_Integrated_Webcam_HD
|
Mas eu quero só com “usb2” ou “usb3” casando com “Product:”.
|
$ grep –E “usb(2|3).*Product:” dmesg.log
[ 1.997342] usb usb2: Product: xHCI Host Controller
[ 2.000103] usb usb3: Product: xHCI Host Controller
|
Sentiu o poder da ferramenta? E você pode aplicar varias combinações com Expressões Regulares, estudaremos no futuro sobre isso.
Podemos criar um arquivo com nosso Regex e usar ele como padrão, alias, podemos colocar varias combinações neste arquivo.
|
$ echo “usb(2|3).*Product:” > meu_regex
$ cat meu_regex
usb(2|3).*Product:
$ grep –f meu_regex –E dmesg.log
[ 1.997342] usb usb2: Product: xHCI Host Controller
[ 2.000103] usb usb3: Product: xHCI Host Controller
|
Usando direto e com pipe
Lembra quando comentei de usar o grep direto e usar ele com qualquer comando um pipe e logo em seguida o grep? Vamos fazer uma pesquisa no /var/log/syslog.1 por quantas ocorrências da string “info” usando cat e o grep direto.
$ time cat /var/log/syslog.1 | grep –c “info”
1027
real 0m0.011s
user 0m0.005s
sys 0m0.008s
$ time grep –c “info” /var/log/syslog.1
1027
real 0m0.009s
user 0m0.009s
sys 0m0.000s
|
Agora uma dica legal, para desempenho de uso em grande escala do grep é setar LC_ALL=C antes:
$ strace –c grep –c “info” /var/log/syslog.1
187
% time seconds usecs/call calls errors syscall
——— —————– —————– ————– ————– ————————
27.03 0.000160 11 14 mmap
14.19 0.000084 8 10 read
13.18 0.000078 13 6 open
11.15 0.000066 8 8 mprotect
9.63 0.000057 11 5 5 access
5.57 0.000033 4 9 fstat
4.56 0.000027 3 9 close
3.55 0.000021 11 2 munmap
3.55 0.000021 7 3 brk
3.04 0.000018 18 1 execve
1.52 0.000009 9 1 write
1.35 0.000008 4 2 1 ioctl
1.35 0.000008 8 1 openat
0.34 0.000002 2 1 arch_prctl
——— —————– —————– ————– ————– ————————
100.00 0.000592 72 6 total
$ export LC_ALL=C
$ strace –c grep –c “info” /var/log/syslog.1
187
% time seconds usecs/call calls errors syscall
——— —————– —————– ————– ————– ————————
20.07 0.000114 11 10 read
16.73 0.000095 8 12 mmap
16.20 0.000092 12 8 mprotect
6.87 0.000039 8 5 5 access
6.16 0.000035 9 4 open
6.16 0.000035 18 2 munmap
5.99 0.000034 34 1 execve
5.46 0.000031 10 3 brk
4.40 0.000025 4 7 close
3.87 0.000022 3 7 fstat
2.99 0.000017 17 1 write
2.64 0.000015 15 1 openat
1.94 0.000011 6 2 1 ioctl
0.53 0.000003 3 1 arch_prctl
——— —————– —————– ————– ————– ————————
100.00 0.000568 64 6 total
|
Novamente verificando o tempo apos setar LC_ALL=C.
$ time grep –c “info” /var/log/syslog.1
187
real 0m0.003s
user 0m0.003s
sys 0m0.000s
$ time cat /var/log/syslog.1 | grep –c “info”
187
real 0m0.005s
user 0m0.000s
sys 0m0.009s
|
No meu syslog.1 não deu tanta diferença, mas fazer essa varredura em um aquivo de 500M você notara uma grande diferença.
Conhecemos, aprendemos e devoramos o grep, vimos o grande potencial que ele pode nos oferecer, ainda possui mais recursos e parâmetros que não vimos e pode ser visto com man grep, mas o foco e suas principais funções foi exemplificado aqui.
Espero que tenham gostado e até a próxima!