Самый длинный общий префикс двух строк в bash - PullRequest
29 голосов
/ 07 августа 2011

У меня есть две строки.Для примера они установлены так:

string1="test toast"
string2="test test"

Я хочу найти перекрытие, начинающееся в начале строк.Под перекрытием я подразумеваю строку «test t» в моем примере выше.

# So I look for the command 
command "$string1" "$string2"
# that outputs:
"test t"

Если бы строки были string1="atest toast"; string2="test test", они не имели бы перекрытия, так как проверка начинается с начала, а «a» вначало string1.

Ответы [ 13 ]

1 голос
/ 29 октября 2018

Еще один основанный на питоне ответ, основанный на os.path собственной функции commonprefix функции

#!/bin/bash
cat mystream | python -c $'import sys, os; sys.stdout.write(os.path.commonprefix(sys.stdin.readlines()) + b\'\\n\')'

Longform, это

import sys
import os
sys.stdout.write(
    os.path.commonprefix(sys.stdin.readlines()) + b'\n'
)

/! \ Примечание: весь текст потока будет загружен в память в виде строковых объектов Python, прежде чем будет обработан этим методом


Если требование не буферизовать весь поток в памяти, мы можем использовать коммуникативное свойство и проверку общности префиксов между каждой входной парой

$!/bin/bash
cat mystream | python -c $'import sys\nimport os\nfor line in sys.stdin:\n\tif not os.path.isfile(line.strip()):\n\t\tcontinue\n\tsys.stdout.write(line)\n') | pythoin sys.stdin:\n\tprefix=os.path.commonprefix([line] + ([prefix] if prefix else []))\nsys.stdout.write(prefix)''

Длинная форма

import sys
import os
prefix = None
for line in sys.stdin:
    prefix=os.path.commonprefix(
        [line] + ([prefix] if prev else [])
    )
sys.stdout.write(prefix)

Оба эти метода должны быть бинарно-безопасными, так как в них не требуется ввод / вывод данных для кодирования ascii или utf-8, если вы сталкиваетесь с ошибками кодирования, python 3 переименовывается в sys.stdinв sys.stdin.buffer и sys.stdout в sys.stdout.buffer, который не будет автоматически декодировать / кодировать потоки ввода / вывода при использовании

1 голос
/ 18 октября 2017

Если вы используете другие языки, как насчет python:

cmnstr() { python -c "from difflib import SequenceMatcher
s1, s2 = ('''$1''', '''$2''')
m = SequenceMatcher(None,s1,s2).find_longest_match(0,len(s1),0,len(s2))
if m.a == 0: print(s1[m.a: m.a+m.size])"
}
$ cmnstr x y
$ cmnstr asdfas asd
asd

(от h / t до @ RickardSjogren ответ на переполнение стека 18715688 )

1 голос
/ 07 августа 2011

Чувак, это сложно. Это очень тривиальная задача, но я не знаю, как это сделать с оболочкой:)

вот ужасное решение:

echo "$2" | awk 'BEGIN{FS=""} { n=0; while(n<=NF) {if ($n == substr(test,n,1)) {printf("%c",$n);} n++;} print ""}' test="$1"
...