Eu tenho duas cordas. Para fins de exemplo, eles são definidos assim:
string1="test toast"
string2="test test"
O que eu quero é encontrar a sobreposição começando no início das strings. Com sobreposição, quero dizer a string "test t" no meu exemplo acima.
# I look for the command
command "$string1" "$string2"
# that outputs:
"test t"
Se as strings fossem, string1="atest toast"; string2="test test"
elas não teriam sobreposição desde que a verificação começa no início e o "a" no início de string1
.
bash
text-processing
string
confundir
fonte
fonte
Respostas:
Você pode pensar em uma função como esta, com alguma verificação de erro para adicionar
fonte
[[ -z "$1$2" ]] && return
corrige isso.64
0m0.005s vs 0m0.003s -128
0m0.013s vs 0m0.003s -256
0m0.041s vs 0m0.003s -512
0m0.143s vs 0m0.005s -1024
0m0.421s vs 0m0.009s -2048
0m1.575s vs 0m0.012s -4096
0m5.967s vs 0m0.022s -8192
0m24.693s vs 0m0.049s -16384
1m34.004s vs 0m0.085s -32768
6m34.721s vs 0m0.168s -65536
27m34.012s vs 0m0.370sn
caractere th, é necessário verificar osn
caracteres para verificar se eles não são o byte zero que termina a string. Isso é consistente com o bash sendo incapaz de armazenar um byte zero em uma variável.Isso pode ser feito inteiramente dentro do bash. Embora a manipulação de strings em um loop no bash seja lenta, existe um algoritmo simples que é logarítmico no número de operações do shell, portanto o bash puro é uma opção viável mesmo para strings longas.
A caixa de ferramentas padrão inclui
cmp
para comparar arquivos binários. Por padrão, indica o deslocamento de bytes dos primeiros bytes diferentes. Há um caso especial quando uma string é um prefixo da outra:cmp
produz uma mensagem diferente em STDERR; uma maneira fácil de lidar com isso é usar a string mais curta.Observe que
cmp
opera em bytes, mas a manipulação de string do bash opera em caracteres. Isso faz a diferença nos códigos de idioma multibyte, por exemplo, códigos de idioma usando o conjunto de caracteres UTF-8. A função acima imprime o prefixo mais longo de uma sequência de bytes. Para lidar com cadeias de caracteres com esse método, primeiro podemos converter as cadeias de caracteres em uma codificação de largura fixa. Supondo que o conjunto de caracteres do código de idioma seja um subconjunto de Unicode, o UTF-32 se ajusta à conta.fonte
while char-by-char
, ainda estou esperando por isso enquanto escrevo isso .. o tempo passa .. ainda esperando (talvez haja algo errado com o meu sistema) .. o tempo passa .. deve haver algo errado; são apenas 10.000 iterações! Ah! paciência é uma virtude (talvez uma maldição, neste caso) .. 13m53.755s .. vs, 0m0.322scmp
é o mais rápido (mas não é baseado em caracteres). O próximo éiconv
e, em seguida, a resposta muito respeitosamente rápidabinary-split
. Obrigado Gilles. Levei um ano para chegar a esse ponto, mas antes tarde do que nunca. (PS. 2iconv
erros de digitação no código:$
in=$LC_CTYPE}
e\
inUTF-32) \
) ... PPS. na verdade, a string que mencionei acima tinha mais de 10.000 caracteres. Foi o resultado de {1..10000}, ou seja, 48.894, mas isso não altera o diferencialNo sed, supondo que as strings não contenham caracteres de nova linha:
fonte
\0
. Usandotr
e\0
, o método pode lidar com novas linhas na string, ....{ printf "%s" "$string1" |tr \\n \\0; echo; printf "%s" "$string2" |tr \\n \\0; echo; } | sed -e 'N;s/^\(.*\).*\n\1.*$/\1/' |tr \\0 \\n
sed
método um pouco mais e parece que o uso de referências posteriores dessa maneira (no padrão de pesquisa) é extremamente caro. Ele ainda supera o loop seqüencial de byte a byte (em aproximadamente um fator de 3), mas aqui está um exemplo: para duas seqüências de 32kb (com o último byte sendo diferente), é necessário2m4.880s
, em comparação com a divisão binária de Gilles Método0m0.168s
Isso me parece grosseiro, mas você pode fazê-lo através da força bruta:
Quero que exista um algoritmo inteligente, mas não consigo encontrá-lo com uma breve pesquisa.
fonte