2012-10-19 8 views
5

मुझे रेड स्टूडियो XE2 में हाइपरस्ट्रिंग पार्सवॉर्ड फ़ंक्शन को प्रतिस्थापित करने के लिए डेल्फी फ़ंक्शन बनाने के लिए रेगेक्स सहायता की आवश्यकता है। हाइपरस्ट्रिंग एक बहुत ही उपयोगी स्ट्रिंग लाइब्रेरी थी जिसने कभी यूनिकोड पर कूद नहीं किया। मुझे यह ज्यादातर काम मिल गया है लेकिन यह उद्धरण delimiters का सम्मान नहीं करता है। मुझे नीचे वर्णित फ़ंक्शन के लिए सटीक मिलान होने की आवश्यकता है:रेगेक्स में उद्धृत पाठ को कैसे छोड़ें (या यूनिकोड टेक्स्ट के साथ हाइपरएसटी पारसेवार्ड का उपयोग कैसे करें?)

फ़ंक्शन पार्सवॉर्ड (कॉन्स स्रोत, तालिका: स्ट्रिंग; var अनुक्रमणिका: Integer): स्ट्रिंग;

अनुक्रमिक, एकल चरित्र डिलीमीटर की तालिका का उपयोग करके अनुक्रमिक, बाएं से दाएं टोकन पार्सिंग। उद्धृत तारों के भीतर Delimiters अनदेखा कर रहे हैं। तालिका में उद्धरण delimiters की अनुमति नहीं है।

सूचकांक एक सूचक समारोह के द्वारा अद्यतन (पहला शब्द के लिए '1' को प्रारंभ) अगले शब्द को इंगित करने के लिए है। अगले शब्द को पुनर्प्राप्त करने के लिए, बस पूर्व लौटाए गए इंडेक्स मान का उपयोग करके फ़ंक्शन को फिर से कॉल करें।

नोट: यदि लंबाई (परिणामस्वरूप) = 0, कोई अतिरिक्त शब्द उपलब्ध नहीं है। उद्धृत तारों के भीतर Delimiters अनदेखा कर रहे हैं।

function ParseWord(const Source, Table: String; var Index: Integer):string; 
var 
    RE : TRegEx; 
    match : TMatch; 
    Table2, 
    chars : string; 
begin 
    if index = length(Source) then 
    begin 
    result:= ''; 
    exit; 
    end; 

    // escape the special characters and wrap in a Group 
    Table2 :='['+TRegEx.Escape(Table, false)+']'; 
    RE := TRegEx.create(Table2); 
    match := RE.Match(Source,Index); 
    if match.success then 
    begin 
    result := copy(Source, Index, match.Index - Index); 
    Index := match.Index+match.Length; 
    end 
    else 
    begin 
    result := copy(Source, Index, length(Source)-Index+1); 
    Index := length(Source); 
    end; 
end; 

    while (Length(result)= 0) and (Index<length(Source)) do 
    begin 
    Inc(Index); 
    result := ParseWord(Source,Table, Index); 
    end; 

चियर्स और धन्यवाद: (मेरे जोर)

यह वही है मैं अब तक है।

उत्तर

0

अपने मूल कोड में मैं सीमांकक लिए देख रहा था और मेरे अगले मैच के रूप में करने के लिए सब कुछ ले जा रहा है, लेकिन जब उद्धरण भीतर चीज़ की तलाश में है जो अवधारणा के बाद से जारी नहीं किया था। @ स्टीफन के खोज को नकारने के सुझाव ने मुझे अंततः कुछ काम करने का नेतृत्व किया। एक अतिरिक्त जटिलता जिसे मैंने पहले कभी नहीं बताया है कि हाइपरएसआरटी उद्धरण चरित्र के रूप में कुछ भी उपयोग कर सकता है। डिफ़ॉल्ट डबल कोट है लेकिन आप इसे फ़ंक्शन कॉल के साथ बदल सकते हैं।

मेरे समाधान में मैंने स्पष्ट रूप से कोट कोटर को दोहरे उद्धरण के रूप में हार्डकोड किया है, जो मेरे अपने उद्देश्यों के अनुरूप है, लेकिन क्वाइंटचर को वैश्विक बनाने और इसे किसी अन्य फ़ंक्शन के भीतर सेट करना मुश्किल होगा। मैंने इसे सिंगल कोट (एएससीआई 3 9) के साथ सफलतापूर्वक परीक्षण किया है, जो डेल्फी में मुश्किल होगा।

function ParseWord(const Source, Table: String; var Index: Integer):string; 
var 
    RE : TRegEx; 
    match : TMatch; 
    Table2: string; 
    Source2 : string; 
    QuoteChar : string; 
begin 
    if index = length(Source) then 
    begin 
    result:= ''; 
    exit; 
    end; 

    // escape the special characters and wrap in a Group 
    QuoteChar := #39; 
    Table2 :='[^'+TRegEx.Escape(Table, false)+QuoteChar+']*|'+QuoteChar+'.*?'+QuoteChar ; 
    Source2 := copy(Source, Index, length(Source)-index+1); 
    match := TRegEx.Match(Source2,Table2); 
    if match.success then 
    begin 
    result := copy(Source2, match.index, match.length); 
    Index := Index + match.Index + match.Length-1; 
    end 
    else 
    begin 
    result := copy(Source, Index, length(Source)-Index+1); 
    Index := length(Source); 
    end; 
    while (Length(result)= 0) and (Index<length(Source)) do 
    begin 
    Inc(Index); 
    result := ParseWord(Source,Table, Index); 
    end; 

end; 

यह समाधान के आसपास उद्धृत तार से उद्धरण वर्ण पट्टी नहीं है, लेकिन मैं अगर यह होना चाहिए या नहीं मेरे अपने मौजूदा कोड से नहीं बता सकता, और मैं Hyperstr मदद से इसका परीक्षण नहीं कर सकता। शायद कोई और जानता है?

+0

मुझे एसओ प्रोटोकॉल के बारे में निश्चित नहीं था कि किसको जवाब देना है। मैंने समाधान को एक अलग उत्तर के रूप में जोड़ा क्योंकि मैं @ स्टीफन के उत्तर पर टिप्पणी के रूप में इसे ठीक से प्रारूपित नहीं कर सका, लेकिन वह निश्चित रूप से मुझे इसका नेतृत्व करता है। – marcp

1

मैं Table2 के लिए इस regex की कोशिश करेंगे:

Table2 := '''[^'']+''|"[^"]+"|[^' + TRegEx.Escape(Table, false) + ']+'; 

डेमो:
इस डेमो अधिक एक POC के बाद से मैं एक ऑनलाइन डेल्फी regex परीक्षक खोजने में असमर्थ था है।

  • सीमांकक space (ASCII कोड 32) और pipe (ASCII कोड 124) पात्र हैं।
  • परीक्षण वाक्य है:

    टोटो कॉक "एलोआ toutou" 'dfg erre' 1245 | coucou "नेस्टर | डेल्फी" "" ''

http://regexr.com?32i81

चर्चा:
मुझे लगता है कि एक उद्धृत स्ट्रिंग एक दो स्ट्रिंग्स (') या दो डबल कोट्स (") से घिरा हुआ एक स्ट्रिंग है। अगर मैं ग़लत हूं तो मेरी गलती सुझाएं।

रेगुलर एक्सप्रेशन से मेल होगा या तो:

  • एक भी उद्धृत स्ट्रिंग
  • एक डबल उद्धृत स्ट्रिंग
  • किसी भी पारित कर दिया सीमांकक द्वारा रचित नहीं एक स्ट्रिंग

ज्ञात बग:
चूंकि मुझे नहीं पता था कि पर्सवॉर्ड स्ट्रिंग के अंदर से निकलने वाले उद्धरण को कैसे संभालता है, रेगेक्स समर्थक नहीं है यह सुविधा नहीं है।

उदाहरण के लिए:

  • इस 'foo''bar' कैसे व्याख्या करने के लिए? => दो टोकन: 'foo' और 'bar' या एक एकल टोकन 'foo''bar'
  • इस मामले के बारे में भी क्या: "foo""bar"? => दो टोकन: "foo" और "bar" या एक एकल टोकन "foo""bar"
+0

यह दिए गए काम के रूप में काम नहीं किया लेकिन मुझे समाधान के लिए नेतृत्व किया। मैं एक अलग प्रविष्टि के रूप में पूरा समाधान शामिल कर रहा हूं, लेकिन सभी क्रेडिट आपके पास जाता है। – marcp

संबंधित मुद्दे