Tengo dos cuerdas Por el bien del ejemplo, se establecen así:
string1="test toast"
string2="test test"
Lo que quiero es encontrar la superposición que comienza en el comienzo de las cadenas. Con superposición me refiero a la cadena "prueba t" en mi ejemplo anterior.
# I look for the command
command "$string1" "$string2"
# that outputs:
"test t"
Si las cadenas estuvieran, string1="atest toast"; string2="test test"
no tendrían superposición ya que el cheque comienza desde el principio y la "a" al comienzo de string1
.
bash
text-processing
string
confundir
fuente
fuente
Respuestas:
Puede pensar en una función como esta, con alguna verificación de error para agregar
fuente
[[ -z "$1$2" ]] && return
lo arregla64
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
carácter th requiere escanearn
caracteres para verificar que no sean el byte cero que termina la cadena. Esto es consistente con que bash no puede almacenar un byte cero en una variable.Esto se puede hacer completamente dentro de bash. Si bien la manipulación de cadenas en un bucle en bash es lenta, existe un algoritmo simple que es logarítmico en la cantidad de operaciones de shell, por lo que bash puro es una opción viable incluso para cadenas largas.
La caja de herramientas estándar incluye
cmp
para comparar archivos binarios. Por defecto, indica el desplazamiento de bytes de los primeros bytes diferentes. Hay un caso especial cuando una cadena es un prefijo de la otra:cmp
produce un mensaje diferente en STDERR; Una manera fácil de lidiar con esto es tomar la cadena que sea más corta.Tenga en cuenta que
cmp
opera en bytes, pero la manipulación de cadenas de bash funciona en caracteres. Esto marca la diferencia en configuraciones regionales de varios bytes, por ejemplo, configuraciones regionales que utilizan el juego de caracteres UTF-8. La función anterior imprime el prefijo más largo de una cadena de bytes. Para manejar cadenas de caracteres con este método, primero podemos convertir las cadenas a una codificación de ancho fijo. Suponiendo que el conjunto de caracteres de la configuración regional es un subconjunto de Unicode, UTF-32 se ajusta a la factura.fuente
while char-by-char
, todavía estoy esperando mientras escribo esto ... el tiempo pasa ... todavía esperando (tal vez hay algo mal con mi sistema) ... el tiempo pasa ... debe haber algo mal; ¡son solo 10,000 iteraciones! Ah! la paciencia es una virtud (quizás una maldición en este caso) .. 13m53.755s .. vs, 0m0.322scmp
es la más rápida (pero no está basada en caracteres). El siguiente esiconv
y luego el muy respectibly rápidabinary-split
respuesta. Gracias Gilles Me llevó un año llegar a este punto, pero más vale tarde que nunca. (Modificaciones de error tipográfico PS 2 eniconv
código:$
adentro=$LC_CTYPE}
y\
adentroUTF-32) \
) ... PPS. en realidad la cadena que mencioné anteriormente tenía más de 10,000 caracteres. Fue el resultado de {1..10000} que es 48,894, pero eso no 'cambia el diferencialEn sed, suponiendo que las cadenas no contienen ningún carácter de nueva línea:
fuente
\0
. Usandotr
y\0
, el método puede manejar nuevas líneas en la cadena, ...{ 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 un poco más, y parece que usar referencias posteriores de esta manera (en el patrón de búsqueda) es muy costoso. Todavía supera el bucle secuencial byte por byte (en un factor aproximado de 3), pero aquí hay un ejemplo: para dos cadenas de 32 kb (con el último byte diferente), toma2m4.880s
, en comparación con la división binaria de Gilles método0m0.168s
Esto me parece crudo, pero puedes hacerlo a través de la fuerza bruta:
Quiero que exista algún algoritmo inteligente, pero no puedo encontrar ninguno con una búsqueda corta.
fuente