2009-06-05 18 views
9

मैं पर्ल में एक रेगेक्स के माध्यम से एक ढीला शब्द रैपिंग सिस्टम बनाने की कोशिश कर रहा हूं। मैं जो चाहूंगा वह लगभग 70 वर्णों के बारे में है, ताकि अगले व्हाइटस्पेस घटना की जांच हो और उस स्थान को एक नई लाइन से बदल दें, और फिर पूरी स्ट्रिंग के लिए ऐसा करें। जिस स्ट्रिंग पर मैं काम कर रहा हूं, उसके पास पहले से ही इसमें नई लाइनें हो सकती हैं, लेकिन न्यूलाइन के बीच पाठ की मात्रा बहुत लंबी होती है।मैं पर्ल में एक स्ट्रिंग को कैसे लपेट सकता हूं?

मैं एक समय में एक चरित्र पाशन या substr अगर मैं कर सकते हैं का उपयोग कर से बचने के लिए चाहते हैं, और मैं के रूप में नए स्ट्रिंग वस्तुओं बनाने के लिए विरोध जगह में इस स्ट्रिंग संपादित करने के लिए पसंद करेंगे। ये केवल वरीयताएं हैं, हालांकि, और यदि मैं इन प्राथमिकताओं को तोड़ने के बिना जो कुछ भी ढूंढ रहा हूं उसे हासिल नहीं कर पा रहा हूं तो यह ठीक है।

विचार?

+1

, वहाँ एक चरित्र \ ख है कि शब्द सीमाओं जो एक छोटे से अधिक मजबूत हो सकता है से मेल खाता है जो चिह्नित होता है सेट है। – jiggy

+2

@jiggy \ b एक वर्ण वर्ग नहीं है, यह शून्य चौड़ाई वाला दावा है। –

+2

इसके अलावा, "जोरदार ढंग से!"विराम चिह्न शब्द के बीच तोड़ सकता है, और यह सिर्फ गलत है ! – Axeman

उत्तर

11
s/(.{70}[^\s]*)\s+/$1\n/ 

पहले 70 अक्षरों का उपभोग करें, फिर प्रक्रिया में सब कुछ कैप्चर करते हुए, अगले व्हाइटस्पेस पर रोकें। फिर, कैप्चर स्ट्रिंग को छोड़ दें, अंत में व्हाइटस्पेस को छोड़कर, एक नई लाइन जोड़ें।

यह गारंटी नहीं है अपने लाइनों 80 अक्षर या कुछ और पर सख्ती से कट जाएगा। इस बात की कोई गारंटी नहीं है कि आखिरी शब्द जो उपभोग करता है वह अरबों वर्ण लंबा नहीं होगा।

+1

मुझे लगता है कि यह बेहतर होगा। {70,80} \ s +, ताकि अगर आपको 71 में स्थान के साथ" एक जैसा "शुरू हो, आपको एक कड़ा लपेटना पड़ता है। – Axeman

+0

@ एक्समन सही है, लेकिन लालची मूल्यांकन (जो जितना संभव हो उतना सामग्री से मिलान करने का प्रयास करता है) के लिए धन्यवाद, आप चाहते हैं। 70 char लाइन लंबाई के लिए {1,70}। मैंने जवाब संपादित किया है ऐसा करने के लिए। –

+1

एक और उन्नत regexp, जो लाइनब्रेक्स को सुदृढ़ रूप से संभाल सकता है (उन्हें उपरोक्त मूलभूत उदाहरण के रूप में मारने के बजाए) होगा/(। {1,70} | \ S {71,}) (?: \ s [^ \ S \ r \ n] * | \ Z)/$ 1 \ n/g'। मैं आधिकारिक उत्तर को सरल रखना चाहता था, इसलिए मैंने इसे छोड़ दिया। –

22

Text::Wrap या Text::Autoformat तरह मॉड्यूल देखें।

अपनी आवश्यकताओं पर निर्भर करता है, यहां तक ​​कि GNU मूल उपयोगिता गुना (1) एक विकल्प हो सकता है।

+1

शायद यह सबसे अच्छा तरीका है - कुछ को छोड़कर पुरातन वाक्यविन्यास का। – Axeman

+0

असल में मैंने पाया कि टेक्स्ट :: लपेटें :: स्मार्ट शब्द एक पंक्ति को तोड़ने से रोकता है यदि कोई शब्द लम्बी है परिभाषित संदेश आकार से आर। – RushPL

7

Welbog का जवाब 70 अक्षरों के बाद पहली अंतरिक्ष में घूमती है। इसमें यह दोष है कि लाइन के अंत के करीब शुरू होने वाले लंबे शब्द एक अतिव्यापी रेखा बनाते हैं। मैं बजाय सुझाव है कि पहले, कहते हैं, 81 पात्रों के अंतर्गत अंतिम अंतरिक्ष में लपेटकर, या पहले अंतरिक्ष में लपेटकर यदि आप एक> 80 चरित्र "शब्द" है, इसलिए है कि केवल सही मायने में अटूट लाइनों लंबा कर रहे हैं:

s/(.{1,79}\S|\S+)\s+/$1\n/g; 

आधुनिक पर्ल में:

s/(?:.{1,79}\S|\S+)\K\s+/\n/g; 
+1

डी ओह! और मैंने इस तरह की चीज कई बार भी की है। – Axeman

5

आप बहुत कुछ नियंत्रण और विश्वसनीयता प्राप्त कर सकते हैं Text::Format

use Text::Format; 
print Text::Format->new({columns => 70})->format($text); 
1

इस का उपयोग करते हुए एक मैं हमेशा उपयोग किया है है।

स्वीकार्य समाधान के विपरीत, यह रैप-लम्बाई (इस मामले में, 75 वर्ण) से पहले लपेट जाएगा, जब तक कि वास्तव में लंबी स्ट्रिंग (जैसे यूआरएल) न हो, उस स्थिति में यह उस स्ट्रिंग को बस उस पर रखेगा इसे तोड़ने के बजाए अपनी लाइन।

s/(?=.{70,})(.{0,70}\n?)()/\1\2\n /g 

यह दूसरा रूप सभी लाइन अंत संभालती है: मैक \ r, यूनिक्स \ N, विंडोज \ r \ n, और टेलीटाइप \ n \ r, लेकिन जो भी इसे का उपयोग करता है के रूप में एक प्रतिस्थापन अभी भी आप क्या डाल पर निर्भर करता है प्रतिस्थापन खंड में: मैंने \ n उपयोग किया है।

s/(?=.{70,})(.{0,70}(?:\r\n?|\n\r?)?)()/\1\2\n /g 

दोनों संस्करणों भी एक अंतरिक्ष से पहले के बाद सभी लिपटे लाइनों इंडेंट: पिछले/जी से पहले स्थान निकाल सकता है, तो आपको लगता है कि नहीं करना चाहती, लेकिन मैं आम तौर पर यह अच्छा लगता है।

खाली स्थान के के बजाय
संबंधित मुद्दे

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