Maio-2017
SOBRE O COMANDO GREP DO LINUX
“Como sempre, pesquisei na internet encontrei informações. Separei as que achei mais interessantes para mim e montei esta anotação para eu usar. Dá para eu ter pelo menos uma noção do que é o comando grep. Espero que minha anotação lhe seja util. Ela é útil para mim.”
O significado do nome é (Globally Search a Regular Expression and Print)
O Grep procura texto em uma string ou dentro de arquivos e mostra linhas, ocorrências. O Grep usa combinações para pesquisar e o resultado da pesquisa pode ser mostrado na tela.
O grep já vem instalado no Linux.
Digitando apenas o comando e dando enter ele não faz nada, mas se digito um parâmetro tipo -V já posso saber a versão do grep que tenho instalado no meu Linux.
$ grep -V
grep (GNU grep) 3.0
Copyright (C) 2017 Free Software Foundation, Inc.
Licença GPLv3+: GNU GPL versão 3 ou superior <http://gnu.org/licenses/gpl.html>.
Este é um software livre: você é livre para alterá-lo e redistribuí-lo.
NÃO HÁ GARANTIAS, na máxima extensão permitida por lei.
Escrito por Mike Haertel e outros, veja <http://git.sv.gnu.org/cgit/grep.git/tree/AUTHORS>
Alguns parâmetros que posso usar e suas respectivas funções:
PARÂMETROS 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
Crio um arquivo chamado palavras.txt coloco um texto dentro e brinco 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
Visualizo o arquivo que criei:
$ 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ê?
Uso o grep para pesquisar pela string “Raspberry“, posso 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 perde performance caso eu realize pesquisa em muitos arquivo ou em um arquivo longo.
$ 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
$ grep “arduino” palavras.txt
arduino
Tenho Arduino escrito de diversas maneiras, então vou executar o grep 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 vou 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 posso fazer obtendo as linhas depois da linha com a string pesquisada.
$ grep “arduino” -A 2 palavras.txt
arduino
ARDUINO
IDEArduino
Posso 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 eu 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
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.
Vou brincar com outros parâmetros. Desta vez vou 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.
Preparo 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.
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
Caso eu 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
Agora com o básico de Expressões Regulares, e como exemplo usarei 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. Vou trabalhar em cima extendendo os recursos de Regex da expressão, por exemplo quero somente as linhas que contenham usb2 OU usb3, aplicando a lógica 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
Vou pesquisar por uma linha que contenha “usb” E tambem “Product:”, vou 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
Posso aplicar varias combinações com Expressões Regulares.
Posso criar um arquivo com o meu 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
Vou usar o grep direto e usar ele com qualquer comando um pipe e logo em seguida o grep.
Vou 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
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ê notará uma grande diferença.
Até Breve.
Fonte
Fonte2
.