grep
é o comando que implementa o comando g/<RE>/p
em ed
/ ex
(daí seu nome), isto é, p
rints as linhas que correspondem a um determinado r
egular e
xpression (regex ou regexp para breve).
Aqui, '^[^:]\+::'
é a expressão regular (citada para que o shell não trate alguns desses caracteres especialmente). Mais precisamente (como existem várias implementações de grep
e a maioria pode lidar com diversas variantes de expressões regulares), é uma expressão regular GNU Basic.
Expressões regulares são padrões usados para corresponder strings. grep
compara o conteúdo de cada linha com esse padrão e imprime os que correspondem.
-
^
é o operador de expressão regular básica que corresponde ao início da string a ser correspondida. Dizemos que ela ancora a pesquisa no início da string, caso contrário, a pesquisa estaria em qualquer lugar dentro da linha. -
[^:]
corresponde a qualquer caractere, mas:
-
\+
é um operador regexp não-padrão específico do GNU (embora atualmente encontramos outras implementações suportando-o) que significa um ou mais dos átomos anteriores. É uma mão curta para o operador regex padrão\{1,\}
basic. -
:
não é especial e corresponde a si mesmo.
Portanto, o regexp corresponde as linhas que iniciam com uma sequência de um ou mais caracteres diferentes de :
seguido por dois :
caracteres.
No contexto de /etc/shadow
, isso significa que ele corresponde a entradas com pelo menos 3 campos e onde o campo nome de usuário não está vazio, mas o campo de senha está vazio (o que geralmente significa usuários que podem efetuar login sem uma senha). Ele corresponderá a root::
, x::whatever
, mas não a root:x:
ou ::whatever
ou root:
.
grep
também informa se ele correspondeu a qualquer linha com seu status de saída:
- bem-sucedido se houver pelo menos uma correspondência
- falha de outra forma ou se ocorreu um erro.
O status de saída de uma atribuição de shell é o status de saída do último comando executado em uma substituição de comando.
Por exemplo, o status de saída
var=$(exit 2)$(exit 4)
será 4.
Então, aqui você pode fazer:
if lines=$(grep '^[^:]\+::' /etc/shadow); then
printf 'There are users with an empty password:\n%s\n' "$lines"
else
printf 'OK, no user with empty passwords'
fi