Você pode fazer algo como:
<file LC_ALL=C sort |
sed -n 'N;h;s/^\(.*\).*\n.*//p;g;D' |
awk '{l = length}
l > max {max = l; s = $0}
END {print s}'
Classificamos a entrada usando a comparação byte a byte ( sort no código do idioma C) que garante que as linhas com o maior prefixo comum sejam adjacentes.
sed encontra o prefixo comum mais longo entre uma linha e a próxima usando referências anteriores BRE ( \(.*\).*\n sendo uma sequência capturada de caracteres \(.*\) seguido por qualquer número de caracteres .* , uma nova linha \n e a mesma sequência de caracteres capturada anteriormente ), que imprimimos.
awk encontra o mais longo deles (escolhe o primeiro na entrada se houver vários, então será o primeiro na ordem lexical. Use >= em vez de > para obter o último).
Note que ele encontra o prefixo comum mais longo em termos de caracteres . Para tê-lo em termos de bytes , defina $LC_ALL para C para todos os 3 comandos, não apenas sort . Então, por exemplo, nas localidades UTF-8, em vez de encontrar o 2 caractere St como o prefixo comum mais longo entre Stéphane e Stábat , os 3 bytes, St<0xc3> onde <0xc3> serão encontrados a primeira metade dos caracteres á e é .
Para tê-lo em termos de cluster grapheme estendido . Por exemplo, para que entre Steps e Stéphane (onde é é expresso como o cluster de grafema de dois caracteres e\u0301 ) encontre St em vez de Ste , você pode recorrer a perl :
<file LC_ALL=C sort |
perl -Mopen=locale -ne '
BEGIN{$prev = <>}
if ("$prev$_" =~ /^(\X*).*\n\b{g}/) {
$l = length($1);
if ($l > $max) {$max = $l; $s = $1}
}
$prev = $_;
END{print "$s\n"}'
(onde \X corresponde a um cluster de grafema estendido e \b{g} an limite de cluster de grafema estendido (para o qual você precisa de perl 5.22.1 ou mais recente)).
Se você quisesse encontrar o prefixo comum mais longo de todas as linhas na entrada (não apenas quaisquer 2 linhas na entrada), como eu inicialmente pensei que você fosse perguntando, isso é respondido naquele outro Q & A aqui .