У меня есть две строки. Для примера они установлены так:
string1="test toast"
string2="test test"
Я хочу найти перекрытие, начинающееся в начале строк. Под перекрытием я подразумеваю строку «test t» в моем примере выше.
# I look for the command
command "$string1" "$string2"
# that outputs:
"test t"
Если бы строки были, string1="atest toast"; string2="test test"
они бы не перекрывались, так как проверка начинается с начала, а "a" в начале string1
.
bash
text-processing
string
кон-е использование
источник
источник
Ответы:
Вы можете думать о такой функции, с некоторой проверкой ошибок, чтобы добавить
источник
[[ -z "$1$2" ]] && return
исправляет это.64
делением Жиля : .. 0m0,005s против 0m0,003s -128
0m0,013s против 0m0,003s -256
0m0,041s против 0m0,003s -512
0m0,143s против 0m0,005s -1024
0m0,421s против 0m0,009s -2048
0m1,575s против 0m0,012s -4096
0m5,967s против 0m0,022s -8192
0m24,693s против 0m0,049s -16384
1m34,004 с против 0m0,085 с -32768
6m34,721 с против 0m0,168 с -65536
27m34,012 с против 0m0,370 сn
символа th требует сканированияn
символов, чтобы убедиться, что они не заканчивают строку нулевым байтом. Это согласуется с тем, что bash не может хранить нулевой байт в переменной.Это можно сделать полностью внутри Bash. Хотя манипулирование строками в цикле в bash является медленным, существует простой алгоритм, логарифмирующий по количеству операций оболочки, поэтому чистый bash является приемлемым вариантом даже для длинных строк.
Стандартный набор инструментов включает
cmp
в себя для сравнения двоичных файлов. По умолчанию, это указывает смещение байта первых отличающихся байтов. Существует особый случай, когда одна строка является префиксом другой:cmp
создает другое сообщение в STDERR; Самый простой способ справиться с этим - взять самую короткую строку.Обратите внимание, что он
cmp
работает с байтами, но манипулирование строками в bash работает с символами. Это имеет значение для многобайтовых локалей, например, для локалей, использующих набор символов UTF-8. Вышеуказанная функция печатает самый длинный префикс байтовой строки. Чтобы обработать строки символов с помощью этого метода, мы можем сначала преобразовать строки в кодировку с фиксированной шириной. Предполагая, что набор символов локали является подмножеством Unicode, UTF-32 отвечает всем требованиям.источник
while char-by-char
, я все еще жду этого, когда я пишу это ... проходит время ... все еще жду (может быть, есть что-то не так с моей системой) .. время идет .. должно быть что-то не так; это всего 10000 иттераций! Ах! терпение - добродетель (возможно, проклятие в этом случае) .. 13м53.755с .. против 0м0.322сcmp
это самый быстрый (но не основанный на символах). Следующим являетсяiconv
и то очень respectibly быстрыйbinary-split
ответ. Спасибо, Жиль. Мне потребовался год, чтобы добраться до этой точки, но лучше поздно, чем никогда. (PS. 2 опечатки модов вiconv
коде:$
в=$LC_CTYPE}
и\
вUTF-32) \
) ... PPS. на самом деле строка, о которой я упоминал выше, была длиннее 10 000 символов. Это был результат {1..10000}, то есть 48 894, но это не «меняет дифференциал»В sed предполагается, что строки не содержат символов новой строки:
источник
\0
. С помощью методаtr
and\0
можно обрабатывать символы новой строки в строке ....{ 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
метод немного дальше, и кажется, что использование обратных ссылок таким образом (в шаблоне поиска) чрезвычайно дорого. Он по-прежнему превосходит последовательное побитовое зацикливание (примерно в 3 раза), но вот пример: для двух строк по 32 КБ (с разным последним байтом) требуется2m4.880s
, по сравнению с двоичным делением Жиля метод0m0.168s
Это кажется мне грубым, но вы можете сделать это с помощью грубой силы:
Я хочу, чтобы существовал какой-нибудь умный алгоритм, но я не могу найти ни одного с помощью короткого поиска.
источник