"Sed" yerine enterpolasyonlu dizginin tüm metakarlardan kaçmasını nasıl sağlar?


21

Bir metin akışı okur ve daha sonra ile çalıştırılan sed komutları bir dosya oluşturur bir komut dosyası var sed -f. Oluşturulan sed komutları aşağıdaki gibidir:

s/cid:image002\.gif@01CC3D46\.926E77E0/https:\/\/mysite.com\/files\/1922/g
s/cid:image003\.gif@01CC3D46\.926E77E0/https:\/\/mysite.com\/files\/1923/g
s/cid:image004\.jpg@01CC3D46\.926E77E0/https:\/\/mysite.com\/files\/1924/g

sedKomutları üreten komut dosyasının aşağıdaki gibi olduğunu varsayın :

while read cid fileid
do
    cidpat="$(echo $cid | sed -e s/\\./\\\\./g)"
    echo 's/'"$cidpat"'/https:\/\/mysite.com\/files\/'"$fileid"'/g' >> sedscr
done

cidDizedeki tüm normal ifade meta karakterlerinin kaçmasını ve uygun şekilde enterpolasyonunu sağlamak için komut dosyasını nasıl geliştirebilirim ?

Yanıtlar:


24

Bir skomutun sed(burada $lhsve $rhssırasıyla) sol tarafında ve sağ tarafında kullanılacak değişkenlerden kaçmak için şunları yaparsınız:

escaped_lhs=$(printf '%s\n' "$lhs" | sed 's:[][\/.^$*]:\\&:g')
escaped_rhs=$(printf '%s\n' "$rhs" | sed 's:[\/&]:\\&:g;$!s/$/\\/')

sed "s/$escaped_lhs/$escaped_rhs/"

Yeni $lhssatır karakteri içeremeyeceğini unutmayın .

Yani, LHS'de, tüm normal ifade operatörlerinden ( ][.^$*), kaçan karakterin kendisinden ( \) ve ayırıcıdan ( /) kaçın .

RHS'de, yalnızca &ayırıcıdan, ayırıcıdan, ters eğik çizgiden ve yeni satır karakterinden (son satır ( $!s/$/\\/) hariç her satırın sonuna bir ters eğik çizgi ekleyerek yaptığınız) kaçmanız gerekir .

Yani kullandığınız varsayılmaktadır /senin bir ayırıcı olarak sed skomutlar ve etkinleştirmek olmadığını Genişletilmiş RE'lerı ile -r(GNU sed/ ssed/ ast/ busybox sed) ya da -E(BSD, astson GNU, son busybox) ya da PCREs ile -R( ssed) veya Artırılmış RE'ler ile -A/ -X( ast) hangi hepsinde ekstra RE operatörleri vardır.

Rasgele verilerle çalışırken bazı temel kurallar:

  • Kullanma echo
  • değişkenlerini teklif et
  • yerel ayarın etkisini düşünün (özellikle karakter kümesi: kaçan sed komutların, sedörneğin kaçan dizeleri (ve aynı sedkomutla) kullanan komutla aynı yerel ayarda çalıştırılması önemlidir.
  • yeni satır karakterini unutmayın (burada $lhsherhangi bir içerik olup olmadığını kontrol etmek ve işlem yapmak isteyebilirsiniz ).

Başka bir seçenek de , dizeleri ortamın perlyerine kullanmak sedve ortamdan geçirmek ve dizeleri tam anlamıyla almak için \Q/ \E perlregexp işleçlerini kullanmaktır :

A="$lhs" B="$rhs" perl -pe 's/\Q$ENV{A}\E/$ENV{B}/g'

perl(varsayılan olarak), yerel ayarın karakter kümesinden etkilenmez, çünkü yukarıdaki gibi, dizeleri yalnızca kullanıcı için hangi karakterleri (varsa) temsil edebileceklerini önemsemeden bayt dizileri olarak görür. İle sed, tüm komutlar için yerel ayarı Cile sabitleyerek aynı şeyi başarabilirsiniz (ancak bu, varsa hata mesajlarının dilini de etkiler).LC_ALL=Csed


Çift tırnaktan kaçmam gerekirse ne olur?
Menon

@Menon, çift tırnak için özel değil sed, onlardan kaçmanıza gerek yok.
Stéphane Chazelas

Bu joker karakter kullanarak desen eşleştirme için kullanılamaz, değil mi?
Menon

@Menon, no, joker desen eşleşmesi ile find's gibi -namenormal ifadelerden farklı. Orada sadece kaçmak ?, *ters eğik çizgi ve[
Stéphane Chazelas
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.