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