Saya punya dua string. Demi contoh mereka ditetapkan seperti ini:
string1="test toast"
string2="test test"
Yang saya inginkan adalah menemukan tumpang tindih mulai dari awal string. Dengan tumpang tindih maksud saya string "test t" dalam contoh saya di atas.
# I look for the command
command "$string1" "$string2"
# that outputs:
"test t"
Jika string adalah string1="atest toast"; string2="test test"
mereka tidak akan tumpang tindih sejak cek dimulai dari awal dan "a" di awal string1
.
bash
text-processing
string
membingungkan
sumber
sumber
Jawaban:
Anda dapat memikirkan fungsi seperti ini, dengan beberapa pemeriksaan kesalahan untuk ditambahkan
sumber
[[ -z "$1$2" ]] && return
memperbaikinya.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
karakter th memerlukan pemindaiann
karakter untuk memeriksa bahwa mereka bukan nol-byte penghentian string. Ini konsisten dengan bash karena tidak dapat menyimpan nol-byte dalam suatu variabel.Ini bisa dilakukan sepenuhnya di dalam bash. Meskipun melakukan manipulasi string dalam satu loop dalam bash lambat, ada algoritma sederhana yang logaritmik dalam jumlah operasi shell, jadi bash murni adalah pilihan yang layak bahkan untuk string panjang.
Kotak alat standar termasuk
cmp
untuk membandingkan file biner. Secara default, ini menunjukkan offset byte dari byte pertama yang berbeda. Ada kasus khusus ketika satu string adalah awalan dari yang lain:cmp
menghasilkan pesan berbeda pada STDERR; cara mudah untuk mengatasinya adalah dengan mengambil string mana yang paling pendek.Catatan yang
cmp
beroperasi pada byte, tetapi manipulasi string bash beroperasi pada karakter. Ini membuat perbedaan dalam lokal multibyte, untuk contoh lokal menggunakan set karakter UTF-8. Fungsi di atas mencetak awalan terpanjang dari string byte. Untuk menangani string karakter dengan metode ini, pertama-tama kita dapat mengkonversi string ke encoding dengan lebar tetap. Dengan asumsi set karakter lokal adalah bagian dari Unicode, UTF-32 sesuai dengan tagihan.sumber
while char-by-char
, saya masih menunggu saat saya menulis ini .. waktu berlalu .. masih menunggu (mungkin ada sesuatu salah dengan sistem saya) .. waktu berlalu .. pasti ada sesuatu yang salah; hanya 10.000 iterasi! Ah! kesabaran adalah suatu kebajikan (mungkin kutukan dalam kasus ini) .. 13m53.755s .. vs, 0m0.322scmp
adalah yang tercepat (tetapi tidak berbasis char). Selanjutnya adalahiconv
dan kemudian sangat respectibly cepatbinary-split
jawaban. Terima kasih Gilles. Butuh waktu setahun bagi saya untuk sampai ke titik ini, tetapi lebih baik terlambat daripada tidak sama sekali. (PS. 2 kesalahan ketik dalamiconv
kode:$
masuk=$LC_CTYPE}
dan\
masukUTF-32) \
) ... PPS. sebenarnya string yang saya sebutkan di atas lebih dari 10.000 karakter. Itu adalah hasil dari {1..10000} yaitu, 48.894, tetapi itu tidak 'mengubah diferensialSelain itu, dengan asumsi string tidak mengandung karakter baris baru:
sumber
\0
. Menggunakantr
dan\0
, metode ini dapat menangani baris baru dalam 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
metode ini sedikit lebih jauh, dan tampaknya menggunakan kembali-referensi dengan cara ini (dalam pola pencarian) sangat mahal. Itu masih mengungguli perulangan byte-by-byte berurutan (oleh kira-kira faktor 3), tetapi di sini adalah sebuah contoh: untuk dua string 32kb (dengan byte terakhir yang berbeda), dibutuhkan2m4.880s
, dibandingkan dengan binary-split Gilles metode0m0.168s
Ini kelihatannya kasar bagi saya, tetapi Anda bisa melakukannya melalui kekerasan:
Saya ingin beberapa algoritma pintar ada, tetapi saya tidak dapat menemukannya dengan pencarian singkat.
sumber