Mam dwa sznurki. Dla przykładu są one ustawione następująco:
string1="test toast"
string2="test test"
Chcę znaleźć zakładkę zaczynającą się na początku ciągów. Przez nakładanie mam na myśli ciąg „test t” w moim powyższym przykładzie.
# I look for the command
command "$string1" "$string2"
# that outputs:
"test t"
Gdyby łańcuchy były string1="atest toast"; string2="test test"
, nie zachodziłyby one na siebie, ponieważ kontrola zaczyna się od początku, a „a” na początku string1
.
bash
text-processing
string
dezorientować
źródło
źródło
Odpowiedzi:
Możesz pomyśleć o takiej funkcji z dodaniem kontroli błędów
źródło
[[ -z "$1$2" ]] && return
naprawia to.64
0m0,005s vs 0m0,003s -128
0m0,013s vs 0m0,003s -256
0m0,041s vs 0m0,003s -512
0m0,133 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
znaku th wymaga skanowanian
znaków w celu sprawdzenia, czy nie są one kończącym ciąg zerowy bajtem. Jest to spójne z tym, że bash nie może zapisać zera w bajcie.Można to zrobić całkowicie w bashu. Chociaż manipulowanie łańcuchem w pętli w bash jest powolne, istnieje prosty algorytm logarytmiczny w liczbie operacji powłoki, więc czyste bash jest realną opcją nawet dla długich łańcuchów.
Standardowy zestaw narzędzi obejmuje
cmp
porównywanie plików binarnych. Domyślnie wskazuje przesunięcie bajtów pierwszych różnych bajtów. Istnieje szczególny przypadek, gdy jeden ciąg znaków jest przedrostkiem drugiego:cmp
generuje inny komunikat na STDERR; łatwym sposobem na poradzenie sobie z tym jest wybranie dowolnego krótszego ciągu.Zauważ, że
cmp
działa na bajtach, ale manipulacja ciągami bash działa na znakach. To robi różnicę w ustawieniach wielobajtowych, na przykład ustawień regionalnych wykorzystujących zestaw znaków UTF-8. Funkcja powyżej wyświetla najdłuższy prefiks ciągu bajtów. Aby obsłużyć ciągi znaków za pomocą tej metody, możemy najpierw przekonwertować ciągi znaków na kodowanie o stałej szerokości. Zakładając, że zestaw znaków lokalizacji jest podzbiorem Unicode, UTF-32 pasuje do rachunku.źródło
while char-by-char
, wciąż czekam na to, kiedy to piszę ... czas mija .. wciąż czekam (może coś jest źle z moim systemem) .. czas płynie .. musi być coś nie tak; to tylko 10 000 iteracji! Ach! cierpliwość jest cnotą (być może przekleństwem w tym przypadku) .. 13m53.755s .. vs, 0m0.322scmp
jest najszybszy (ale nie jest oparty na znakach). Kolejnym jesticonv
i to bardzo respectibly szybkabinary-split
odpowiedź. Dzięki Gilles. Dotarcie do tego punktu zajęło mi rok, ale lepiej późno niż wcale. (PS. 2 modyfikacje literówek wiconv
kodzie:$
in=$LC_CTYPE}
i\
inUTF-32) \
) ... PPS. tak naprawdę ciąg, o którym wspomniałem powyżej, był dłuższy niż 10 000 znaków. Był to wynik {1..10000}, który wynosi 48 894, ale to nie zmienia różnicyW sed, zakładając, że ciągi nie zawierają żadnych znaków nowej linii:
źródło
\0
. Za pomocątr
i\0
, metoda może obsłużyć{ 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
metodę nieco dalej i wydaje się, że użycie referencji w ten sposób (we wzorcu wyszukiwania) jest niezwykle drogie. Nadal przewyższa sekwencyjne zapętlenie bajt po bajcie (o współczynnik około 3), ale oto przykład: dla dwóch ciągów 32kb (z ostatnim bajtem innym), zajmuje to2m4.880s
, w porównaniu do podziału binarnego Gillesa metoda0m0.168s
Wydaje mi się to prymitywne, ale możesz to zrobić brutalną siłą:
Chcę, aby istniał jakiś sprytny algorytm, ale nie mogę go znaleźć za pomocą krótkiego wyszukiwania.
źródło