Bom caminho
Normalmente você não pode fazer isso com o grep, mas pode usar outras ferramentas. O AWK já foi mencionado, mas você também pode usar o sed
seguinte:
sed -e '1p' -e '/youpattern/!d'
Como funciona:
O utilitário Sed trabalha em cada linha individualmente, executando comandos especificados em cada uma delas. Você pode ter vários comandos, especificando várias -e
opções. Podemos acrescentar cada comando com um parâmetro range que especifica se esse comando deve ser aplicado a uma linha específica ou não.
"1p" é o primeiro comando. Ele usa o p
comando que normalmente imprime todas as linhas. Mas o anexamos com um valor numérico que especifica o intervalo ao qual ele deve ser aplicado. Aqui, usamos o 1
que significa primeira linha. Se você quiser imprimir mais linhas, poderá usar x,yp
onde x
está a primeira linha a ser impressa, a y
última linha a ser impressa. Por exemplo, para imprimir as 3 primeiras linhas, você usaria1,3p
O próximo comando é o d
que normalmente exclui todas as linhas do buffer. Antes deste comando, colocamos yourpattern
entre dois /
caracteres. Essa é a outra maneira (primeiro foi especificar em quais linhas, como fizemos com o p
comando), de endereçar as linhas nas quais o comando deve estar em execução. Isso significa que o comando funcionará apenas para as linhas correspondentes yourpattern
. Exceto, usamos !
caractere antes do d
comando que inverte sua lógica. Portanto, agora ele removerá todas as linhas que não correspondem ao padrão especificado.
No final, o sed imprimirá todas as linhas restantes no buffer. Mas removemos as linhas que não correspondem ao buffer, para que apenas as linhas correspondentes sejam impressas.
Resumindo: imprimimos a primeira linha e excluímos todas as linhas que não correspondem ao nosso padrão da entrada. Resto das linhas são impressos (para que apenas as linhas que fazem corresponder ao padrão).
Problema de primeira linha
Como mencionado nos comentários, há um problema com essa abordagem. Se o padrão especificado corresponder também à primeira linha, ele será impresso duas vezes (uma vez por p
comando e uma vez por causa de uma correspondência). Podemos evitar isso de duas maneiras:
Adicionando 1d
comando depois 1p
. Como já mencionei, o d
comando exclui as linhas do buffer e especificamos seu intervalo pelo número 1, o que significa que ele excluirá apenas a primeira linha. Então o comando seriased -e '1p' -e '1d' -e '/youpattern/!d'
Usando o 1b
comando, em vez de 1p
. É um truque. b
O comando nos permite pular para outro comando especificado por um rótulo (dessa maneira, alguns comandos podem ser omitidos). Mas se esse rótulo não for especificado (como no nosso exemplo), ele simplesmente pula para o final dos comandos, ignorando o restante dos comandos da nossa linha. Portanto, no nosso caso, o último d
comando não removerá essa linha do buffer.
Exemplo completo:
ps aux | sed -e '1b' -e '/syslog/!d'
Usando ponto e vírgula
Algumas sed
implementações podem economizar digitação usando ponto-e-vírgula para separar comandos, em vez de usar várias -e
opções. Portanto, se você não se importa em ser portátil, o comando seria ps aux | sed '1b;/syslog/!d'
. Funciona pelo menos em GNU sed
e busybox
implementações.
Maneira louca
Aqui está, no entanto, uma maneira bastante louca de fazer isso com o grep. Definitivamente não é o ideal, estou publicando isso apenas para fins de aprendizado, mas você pode usá-lo, por exemplo, se não tiver nenhuma outra ferramenta no seu sistema:
ps aux | grep -n '.*' | grep -e '\(^1:\)\|syslog'
Como funciona
Primeiro, usamos a -n
opção para adicionar números de linha antes de cada linha. Queremos numerar todas as linhas com as quais estamos combinando .*
- qualquer coisa, até a linha vazia. Como sugerido nos comentários, também podemos combinar '^', o resultado é o mesmo.
Então, estamos usando expressões regulares estendidas para que possamos usar \|
caracteres especiais que funcionam como OR. Então, combinamos se a linha começa com 1:
(primeira linha) ou contém nosso padrão (nesse caso, é syslog
).
Problema de números de linha
Agora, o problema é que estamos obtendo esses números de linha feios em nossa saída. Se este for um problema, podemos removê-los com cut
, desta forma:
ps aux | grep -n '.*' | grep -e '\(^1:\)\|syslog' | cut -d ':' -f2-
-d
opção especifica delimitador, -f
especifica campos (ou colunas) que queremos imprimir. Portanto, queremos cortar cada linha de cada :
caractere e imprimir apenas a segunda e todas as colunas subseqüentes. Isso efetivamente remove a primeira coluna com seu delimitador e é exatamente isso que precisamos.
ack
são tão úteis, e por queperl
passado disparoused
,awk
etc. em popularidade: é importante para as partes para resumir em um todo coerente.