regex - "परिवर्तनीय लंबाई लागू नहीं दिखती" लेकिन यह परिवर्तनशील लंबाई नहीं है




perl (3)

ऐसा इसलिए है क्योंकि st एक संयुक्ताक्षर हो सकता है। ऐसा ही fi और ff होता है:

#!/usr/bin/perl
use warnings;
use strict;

use utf8;

my $fi = 'fi';
print $fi =~ /fi/i;

तो कल्पना कीजिए कि fi|fi कहाँ, वास्तव में, विकल्प की लंबाई समान नहीं है।

मैं एक बहुत पागल regex कि मैं निदान करने की कोशिश कर रहा हूँ। यह बहुत लंबा है, लेकिन मैंने इसे केवल निम्नलिखित स्क्रिप्ट तक काट दिया है। स्ट्रॉबेरी पर्ल v5.26.2 का उपयोग करके चलाएँ।

use strict;
use warnings;

my $text = "M Y H A P P Y T E X T";
my $regex = '(?i)(?<!(Mon|Fri|Sun)day |August )abcd(?-i)';

if ($text =~ m/$regex/){
    print "true\n";
}
else {
    print "false\n";
}

यह त्रुटि देता है "वैरिएबल लंबाई दिखावे को रेगेक्स में लागू नहीं किया गया है।"

मुझे उम्मीद है कि आप कई मुद्दों के साथ मदद कर सकते हैं:

  1. मैं यह नहीं देखता कि यह त्रुटि क्यों होगी, क्योंकि सभी संभावित खोज मान 7 वर्ण हैं: "सोमवार", "शुक्रवार", "रविवार", "अगस्त"।
  2. मैंने खुद इस रेगेक्स को नहीं लिखा है, और मुझे यकीन नहीं है कि वाक्यविन्यास (?i) और (?-i) व्याख्या कैसे करें। जब मैं (?i) से छुटकारा पाता हूं तो वास्तव में त्रुटि दूर हो जाती है। पर्ल रेगेक्स के इस भाग की व्याख्या कैसे करेगा? मुझे लगता है कि पहले दो पात्रों का मूल्यांकन "वैकल्पिक शाब्दिक कोष्ठक" के लिए किया जाता है, सिवाय इसके कि कोष्ठक बच नहीं जाता है और इस मामले में भी मुझे एक अलग वाक्यविन्यास त्रुटि मिलेगी क्योंकि समापन कोष्ठक तब मेल नहीं खाते होंगे।
  3. यह व्यवहार पर्ल 5.16.3_64 और 5.26.1_64 के बीच कहीं से शुरू होता है, कम से कम स्ट्रॉबेरी पर्ल में। पूर्व संस्करण कोड के साथ ठीक है, बाद वाला नहीं है। इसकी शुरुआत क्यों हुई?

मैंने आपकी समस्या को कम कर दिया है:

my $text = 'M Y H A P P Y T E X T';
my $regex = '(?<!st)A';
print ($text =~ m/$regex/i ? "true\n" : "false\n");

/i (केस असंवेदनशील) संशोधक की उपस्थिति और कुछ वर्ण संयोजनों जैसे "ss" या "st" उपस्थिति के कारण, जिसे Typographic_ligature द्वारा प्रतिस्थापित किया जा सकता है, क्योंकि यह एक चर लंबाई ( /August/i दोनों उदाहरण के लिए मेल खाता है AUGUST (6 अक्षर) और august (5 वर्ण, अंतिम एक U + FB06))।

हालाँकि यदि हम /i (केस असंवेदनशील) संशोधक को हटाते हैं तो यह काम करता है क्योंकि टाइपोग्राफिक लिगचर का मिलान नहीं किया जाता है।

हल: एक संशोधक का प्रयोग करें अर्थात:

/(?<!st)A/iaa

या अपने regex में:

my $text = 'M Y H A P P Y T E X T';
my $regex = '(?<!(Mon|Fri|Sun)day |August )abcd';
print ($text =~ m/$regex/iaa ? "true\n" : "false\n");

प्रति से:

ASCII / गैर-ASCII मैचों (जैसे "k" को "\ N {KELVIN SIGN}" से मना करने के लिए), "a" दो बार, उदाहरण के लिए /aai या /aia निर्दिष्ट करें। ("A" की पहली घटना \d , आदि को प्रतिबंधित करती है, और दूसरी घटना "/ i" प्रतिबंध को जोड़ती है।) लेकिन, ध्यान दें कि ASCII सीमा के बाहर कोड बिंदु /i मिलान के लिए यूनिकोड नियमों का उपयोग करेंगे, इसलिए। संशोधक वास्तव में चीजों को केवल ASCII तक सीमित नहीं करता है; यह सिर्फ ASCII और गैर-ASCII के इंटरमिक्सिंग को मना करता है

बारीकी से संबंधित चर्चा यहाँ देखें


st को character या रूप में 1-वर्ण शैलीगत संयुक्ताक्षर में दर्शाया जा सकता है, इसलिए इसकी लंबाई 2 या 1 हो सकती है।

बश कमांड का उपयोग करके पर्ल की पूरी सूची 2 → 1-कैरेक्टर लिगचर्स की त्वरित रूप से खोज करना:

$ perl -e 'print $^V'
v5.26.2
$ for lig in {a..z}{a..z}; do \
    perl -e 'print if /(?<!'$lig')x/i' 2>/dev/null || echo $lig; done

ff fi fl ss st

ये क्रमशः respectively, , represent, , और / atures ligatures का प्रतिनिधित्व करते हैं।
(obsoletet का प्रतिनिधित्व करता है, अप्रचलित लंबे s वर्ण का उपयोग करके; यह st मेल खाता है और यह ft मेल नहीं खाता है।)

पर्ल शेष स्टाइलिस्टिक लिगमेंट्स, और को और लिए भी सपोर्ट करता है, हालांकि यह इस संदर्भ में उल्लेखनीय नहीं है क्योंकि लुकबाइंड में पहले से ही और /। के साथ अलग-अलग मुद्दे हैं।

पर्ल की भविष्य की रिलीज़ में अधिक शैलीगत लिगचर शामिल हो सकते हैं, हालांकि वे सभी फ़ॉन्ट-विशिष्ट हैं (जैसे लिनक्स लिबर्टिन में ct और ch लिए शैलीगत लिगचर हैं) या विवादास्पद रूप से शैलीगत (जैसे कि ij लिए डच ij या ll लिए अप्रचलित स्पेनिश))। यह उन उपचारों के लिए उचित नहीं है जो पूरी तरह से विनिमेय नहीं हैं (कोई भी इसके लिए dœs स्वीकार नहीं करेगा), हालांकि अन्य परिदृश्य हैं, जैसे कि dœs इसके अपरकेस फॉर्म के लिए धन्यवाद SS

पर्ल 5.16.3 (और इसी तरह के पुराने संस्करण) केवल ss ((के लिए) पर ठोकर खाते हैं और लुकबाइंड्स में अन्य लिगमेंट्स का विस्तार करने में विफल रहते हैं (उनकी निश्चित चौड़ाई है और मेल नहीं खाएगी)। मैं बगफिक्स की तलाश नहीं करता था कि वास्तव में कौन सा संस्करण प्रभावित होता है।

पर्ल 5.14 ने लिगचर सपोर्ट पेश किया, इसलिए पहले के संस्करणों में यह समस्या नहीं है।

समाधान

/(?<!August)x/i (केवल पहली बार सही तरीके से August से August ) के लिए August :

  • /(?<!Augus[t])(?<!Augu(?=st).)x/i (? /(?<!Augus[t])(?<!Augu(?=st).)x/i (? /(?<!Augus[t])(?<!Augu(?=st).)x/i )).) /(?<!Augus[t])(?<!Augu(?=st).)x/i (बिल्कुल मूल)
  • /(?<!Augu(?aa:st))x/i (बस लुक अहाते में st "ASCII- सुरक्षित" ²) है
  • /(?<!(?aa)August)x/i (संपूर्ण लुकअप "ASCII- सुरक्षित" () है
  • /(?<!August)x/iaa (संपूर्ण रेगेक्स "ASCII-safe" ²) है
  • /(?<!Augus[t])x/i (seeking चाहने वाला संयुक्ताक्षर तोड़ता है)
  • /(?<!Augus.)x/i (थोड़ा अलग, अधिक मेल खाता है)
  • /(?<!Augu(?-i:st))x/i (लुकअप के मामले में संवेदनशील, AugusTx मेल नहीं AugusTx )

केस-असंवेदनशील संशोधक ¹ को हटाने या विभिन्न स्थानों में ASCII- सुरक्षित संशोधक AS को जोड़ने के साथ ये खिलौना, अक्सर regex लेखक को विशेष रूप से चर-चौड़ाई संयुक्ताक्षर के बारे में जानने की आवश्यकता होती है।

पहली भिन्नता (जो केवल एक व्यापक है) दो लुकबाइंड के साथ चर की चौड़ाई से मेल खाती है: पहली छः वर्ण संस्करण के लिए (नीचे कोई उद्धरण नहीं जैसा कि पहले उद्धरण में उल्लेख किया गया है) और दूसरा किसी भी लिगचर के लिए, एक आगे लुकहैड को नियोजित करना (जिसमें शून्य है) चौड़ाई!) st (लिगचर सहित) और फिर एक के साथ अपने एकल चरित्र चौड़ाई के लिए लेखांकन .

perlre दो खंड:

¹ केस-असंवेदनशील संशोधक /i और ligatures

यूनिकोड वर्ण की एक संख्या है जो कई वर्णों के अनुक्रम को /i मेल खाती है। उदाहरण के लिए, "LATIN SMALL LIGATURE FI" को अनुक्रम fi मेल खाना चाहिए। पर्ल वर्तमान में ऐसा करने में सक्षम नहीं है जब कई वर्ण पैटर्न में होते हैं और समूह के बीच विभाजित होते हैं, या जब एक या अधिक मात्रा निर्धारित की जाती है। इस प्रकार

"\N{LATIN SMALL LIGATURE FI}" =~ /fi/i;          # Matches [in perl 5.14+]
"\N{LATIN SMALL LIGATURE FI}" =~ /[fi][fi]/i;    # Doesn't match!
"\N{LATIN SMALL LIGATURE FI}" =~ /fi*/i;         # Doesn't match!
"\N{LATIN SMALL LIGATURE FI}" =~ /(f)(i)/i;      # Doesn't match!

Per ASCII- सुरक्षित संशोधक /aa (पर्ल 5.14+)

एएससीआईआई / गैर-एएससीआईआई मैचों (जैसे कि k साथ \N{KELVIN SIGN} ) को मना करने के लिए, दो बार निर्दिष्ट करें, उदाहरण के लिए /aai या /aia । (पहली घटना \d , आदि को प्रतिबंधित करता है, और दूसरी घटना /i प्रतिबंध जोड़ता है।) लेकिन, ध्यान दें कि ASCII रेंज के बाहर कोड बिंदु /i मिलान के लिए यूनिकोड नियमों का उपयोग करेंगे, इसलिए संशोधक नहीं करता है वास्तव में चीजों को सिर्फ ASCII तक सीमित करना; यह सिर्फ ASCII और गैर-ASCII के इंटरमिक्सिंग को मना करता है।

संक्षेप में, यह संशोधक उन अनुप्रयोगों के लिए सुरक्षा प्रदान करता है जो यूनिकोड के सभी के संपर्क में नहीं आना चाहते हैं। इसे दो बार निर्दिष्ट करने से अतिरिक्त सुरक्षा मिलती है।





perl