Syndrom pochylonej wykałaczki
W programowaniu komputerowym syndrom pochylonej wykałaczki ( LTS ) to sytuacja, w której cytowane wyrażenie staje się nieczytelne, ponieważ zawiera dużą liczbę znaków ucieczki , zwykle odwrotnych ukośników („\”), aby uniknąć kolizji ograniczników .
Oficjalna dokumentacja Perla wprowadziła ten termin do szerszego użycia; tam fraza jest używana do opisania wyrażeń regularnych pasujących do ścieżek w stylu uniksowym , w których elementy są oddzielone ukośnikami /
. Ukośnik jest również używany jako domyślny ogranicznik wyrażenia regularnego, więc aby mógł być użyty dosłownie w wyrażeniu, musi być poprzedzony ukośnikiem odwrotnym \ ,
co prowadzi do częstych ukośników ze znakiem ucieczki reprezentowanych jako \/
. W przypadku podwojenia, jak w adresach URL, daje to \/\/
dla znaku ucieczki //
. Podobne zjawisko występuje w ścieżkach DOS / Windows , gdzie ukośnik odwrotny jest używany jako separator ścieżki, co wymaga podwójnego ukośnika odwrotnego \\
- można go następnie ponownie zmienić w celu wyrażenia regularnego wewnątrz ciągu znaków ze znakiem ucieczki, wymagającego dopasowania \\\\
pojedynczy ukośnik odwrotny. W skrajnych przypadkach, takich jak wyrażenie regularne w łańcuchu ze zmianą znaczenia, dopasowanie jednolitej konwencji nazewnictwa (która zaczyna się od \\
) wymaga 8 ukośników odwrotnych \\\\\\\\
z powodu 2 ukośników odwrotnych, z których każdy ma podwójną zmianę znaczenia.
LTS pojawia się w wielu językach programowania iw wielu sytuacjach, w tym we wzorcach pasujących do identyfikatorów URI (Uniform Resource Identifiers ) oraz w programach wyświetlających tekst w cudzysłowach. Wiele chin należy do tej drugiej kategorii.
Przykład wzoru
Rozważmy następujące wyrażenie regularne Perla, którego celem jest dopasowanie identyfikatorów URI, które identyfikują pliki w katalogu pub witryny
FTP :
m / ftp:\/\/[^\/]*\/pub\/ /
Perl, podobnie jak wcześniej sed , rozwiązuje ten problem, pozwalając wielu innym znakom być ogranicznikami wyrażenia regularnego. Na przykład następujące trzy przykłady są równoważne wyrażeniu podanemu powyżej:
m{ftp://[^/]*/pub/} m#ftp://[^/]*/pub/# m!ftp://[^/]*/pub/!
Lub to wspólne tłumaczenie, aby zamienić ukośniki odwrotne na ukośniki:
tr /\\/ \ //
może być łatwiejszy do zrozumienia, gdy jest napisany w ten sposób:
tr { \\ }{ / }
Przykład cytowanego tekstu
Program Perla do drukowania tagu łącza HTML, w którym adres URL i tekst łącza są przechowywane odpowiednio w zmiennych $url
i $text
, może wyglądać tak. Zwróć uwagę na użycie ukośników odwrotnych, aby uniknąć cudzysłowów:
print "<a href=\"$url\">$text</a>" ;
Używanie pojedynczych cudzysłowów do oddzielania łańcucha nie jest wykonalne, ponieważ Perl nie interpretuje zmiennych wewnątrz łańcuchów ujętych w pojedyncze cudzysłowy. Na przykład poniższy kod nie działałby zgodnie z przeznaczeniem:
drukuj '<a href="$url">$tekst</a>'
Korzystanie z funkcji printf
jest opłacalnym rozwiązaniem w wielu językach (Perl, C , PHP ):
printf ( '<a href="%s">%s</a>' , $url , $text );
Operator qq
w Perlu pozwala na dowolny ogranicznik:
drukuj qq{<a href="$url">$text</a>} ; drukuj qq|<a href="$url">$tekst</a>| ; drukuj qq(<a href="$url">$text</a>) ;
W tym przypadku dokumenty szczególnie dobrze nadają się do ciągów wielowierszowych; jednak dokumenty Perla nie pozwalały na prawidłowe wcięcia przed wersją 5.26. Ten przykład pokazuje składnię Perla:
drukuj << HERE_IT_ENDS ; <a href="$url">$text</a> HERE_IT_ENDS
Inne języki
C#
Język programowania C# obsługuje LTS za pomocą symbolu @
na początku literałów łańcuchowych, przed początkowymi znakami cudzysłowu, np.
string filePath = @"C:\Foo\Bar.txt" ;
zamiast wymagać w inny sposób:
string filePath = "C:\\Foo\\Bar.txt" ;
C++
C ++ 11 dodaje surowe łańcuchy znaków :
std :: string filePath = R " ( C:\Foo\Bar.txt ) " ;
Jeśli ciąg zawiera znaki )"
, można użyć opcjonalnego ogranicznika, takiego jak d
w poniższym przykładzie:
std :: regex re { R " d( s/"\([^"]*\)"/'\1'/g )d " };
Iść
Go wskazuje, że łańcuch jest nieprzetworzony, używając znaku wstecznego jako separatora:
s := `C:\Foo\Bar.txt`
Surowe ciągi znaków mogą zawierać dowolne znaki oprócz kresek wstecznych; nie ma kodu ucieczki dla backticka w nieprzetworzonym łańcuchu. Surowe ciągi mogą również obejmować wiele wierszy, jak w tym przykładzie, gdzie ciągi s
i t
są równoważne:
s := `Ciąg, który obejmuje wiele wierszy.` t := "Ciąg, który\nrozciąga się na wiele\nlinii."
Pyton
Python ma podobną konstrukcję, używając r
:
filePath = r "C:\Foo\Bar.txt"
Można ich również używać razem z potrójnymi cudzysłowami:
przykład = r """Pierwszy wiersz: "C:\Foo\Bar.txt" Drugi wiersz: nic"""
Rubin
Ruby używa pojedynczego cudzysłowu, aby wskazać nieprzetworzony ciąg znaków:
filePath = 'C:\Foo\Bar.txt'
Ma również literały procentowe wyrażeń regularnych z wyborem ogranicznika, takiego jak Perl:
% r {ftp://[^/]*/pub/} % r #ftp://[^/]*/pub/# % r !ftp://[^/]*/pub/!
Rdza
Rust używa wariantu przedrostka r
:
" \x52 " ; // R r"\x52" ; // \x52 r#""foo""# ; // "foo" r##"foo #"# bar"## ; // foo #"# bar
Literał zaczyna się od r
, po którym następuje dowolna liczba #
, po której następuje jeden "
. Dalsze "
zawarte w literale są uważane za część literału , chyba że następuje po nich co najmniej tyle #
, ile użyto po otwarciu r
.
Scala
Scala pozwala na użycie potrójnych cudzysłowów, aby uniknąć nieporozumień:
val filePath = """C:\Foo\Bar.txt""" val pubPattern = """ftp://[^/]*/pub/""" r
Potrójne cudzysłowy pozwalają również na ciągi wielowierszowe, jak pokazano tutaj:
val text = """Pierwsza linia, druga linia."""
Sed
Sed , szczególnie te używające operatora „s”, są bardzo podobne do Perla (sed jest poprzednikiem Perla). Domyślnym ogranicznikiem jest „/”, ale można użyć dowolnego ogranicznika; wartością domyślną jest s / regexp / replacement /
, ale s : regexp : replacement :
jest również poprawną formą. Na przykład, aby dopasować katalog „pub” (jak w przykładzie Perla) i zamienić go na „foo”, domyślnym ustawieniem (z ukośnikami) jest
s / ftp:\/\/[^\/]*\/pub\/ / foo /
Zamiast tego użycie wykrzyknika („!”) jako ogranicznika daje wynik
s ! ftp://[^/]*/pub/ ! fuj !