Uma maneira de fazer isso seria i) remover todas as novas linhas para que a coisa toda seja uma cadeia longa e você evite corresponder as primeiras palavras das frases cujo ponto final anterior estivesse na linha anterior e ii) localizar todas as palavras cuja primeira letra é maiúscula e cujo caractere precedente não é um dos .
, ?
, !
. Por exemplo:
$ tr '\n' ' ' < file | grep -Po '(?<![.!?]) \K[A-Z]\w+'
Mars
Mars
Earth
Italian
Giovanni
Schiaparelli
Red
Planet
E para remover entradas duplicadas:
$ tr '\n' ' ' < file | grep -Po '(?<![.!?]) \K[A-Z]\w+' | sort -u
Earth
Giovanni
Italian
Mars
Planet
Red
Schiaparelli
O tr
substitui as novas linhas por espaços. A opção -P
ativa o suporte à Perreg Compatible Regular Expression (PCRE), que nos fornece os recursos avançados que estamos usando. O -o
significa "imprimir apenas a parte correspondente da linha".
A expressão regular usa um lookbehind negativo ( (?>!foo)
) para garantir que correspondamos apenas a nada, exceto a ?
, !
ou .
, então um espaço e, em seguida, uma letra maiúscula [A-Z]
seguida por um ou mais caracteres de palavra.
Observe que isso falhará se:
- um nome é a primeira palavra do arquivo;
- um nome é a primeira palavra de uma frase;
- você tem nomes compostos como María de Quinto, ele corresponderá a
María
eQuinto
, mas ignorará ode
.
Se o seu grep
não suportar as opções -P
ou -o
, você poderá usar o Perl:
perl -0lne 'print join "\n",(/(?<![.!?]) \K[A-Z]\w+/g)' file | sort -u