2013-09-30 9 views
6

विभाजित किसी इस अजीब व्यवहार की व्याख्या कर सकते हैं: एक स्ट्रिंग मेंपर्ल दिलचस्प व्यवहार

मैं hava पथ और मैं मामले में प्रत्येक बैकस्लैश

my $path = "D:\Folder\AnotherFolder\file.txt"; 

my @folders = split('\', $path); 

के लिए इसे विभाजित करना ऊपर यह नहीं काम नहीं करेगा चाहते हैं यहां तक ​​कि इस तरह बैकस्लैश से बचने यदि:

my @folders = split('\\', $path); 

लेकिन एक regexp के मामले में यह काम करेगा:

my @folders = split(/\\/, $path); 

ऐसा क्यों है?

+2

पथ में आपका भाग्य गलत है। एक डबल उद्धृत स्ट्रिंग में, \ \ फ़ोल्डर 'को एक अनुक्रम अनुक्रम' \ F' के रूप में व्याख्या किया जाता है। – TLP

+4

'विभाजन' के लिए विभाजक पैटर्न के चारों ओर उद्धरणों का उपयोग करना बुरा अभ्यास है क्योंकि यह अर्थशास्त्र को सही ढंग से व्यक्त नहीं करता है और डबल संकलन का कारण बनता है। हमेशा स्लैश का उपयोग करें, जब तक कि आप डिफ़ॉल्ट व्यवहार को चलाने के लिए एकल-स्थान स्ट्रिंग को पास नहीं करना चाहते हैं, जब '' सही विकल्प है। – Borodin

+0

@ टीएलपी हाँ मुझे पता है, मैं आमतौर पर पथ के लिए केवल एक उद्धरण डालता हूं। धन्यवाद –

उत्तर

2

आप चलाकर प्रलेखन को देखें, तो:

perldoc -f split 

आप तर्क के तीन रूपों देखेंगे कि split ले जा सकते हैं:

split /PATTERN/,EXPR,LIMIT 
split /PATTERN/,EXPR 
split /PATTERN/ 

इसका मतलब यह है कि जब भी आप split स्ट्रिंग के रूप पारित पहला तर्क, perl इसे रेगेक्स में जोड़ रहा है।

अगर हम चेतावनी जब re.pl में कुछ इस तरह करने का प्रयास कर हम मिल को देखो:

$ my $string_with_backslashes = "Hello\\there\\friend"; 
Hello\there\friend 
$ my @arry = split('\\', $string_with_backslashes); 
Compile error: Trailing \ in regex m/\/ at (eval 287) line 6. 

हम देखते हैं कि पहले '\\' बैकस्लैश एक वास्तविक बैकस्लैश है, जो करने के लिए मूल्यांकन करता है, जिसके बाद बच अंतर्वेशित है एक बैकस्लैश

split तो बैकस्लैश हम दे दिया डालता है, और एक regex के लिए यह coerces के रूप में अगर हम लिखा था:

$ my @arry = split(/\/, $string_with_backslashes); 

जो केवल एक ही बैकस्लैश जो केवल बचने के रूप में व्याख्या की है क्योंकि वहाँ काम नहीं करता है इसके बाद आगे की स्लैश (/ को समाप्त किए बिना) यह दिखाने के लिए कि रेगेक्स समाप्त हो गया है।

+0

समझ नहीं पाया था, असल में, अगर यह स्लैश से बच रहा था, तो आपको 'खोज पैटर्न समाप्त नहीं हुआ' त्रुटि मिलेगी, जिसका अर्थ ऑपरेटर टूटा हुआ था । यह कुछ और है। – TLP

+3

अधिक स्पष्ट रूप से: तारों और regexes भागने के लिए अलग-अलग नियम हैं। यदि रेगेक्स के स्थान पर एक स्ट्रिंग का उपयोग किया जाता है, तो स्ट्रिंग अक्षर डबल से बचने से पीड़ित होते हैं। – amon

+0

@ user1436026 मैंने पेल्डड को पढ़ा था, लेकिन आंतरिक कार्य को समझ नहीं पाया था, यह नहीं पता था कि जो कुछ भी आप डालते हैं, वह अभी भी बदल जाता है और –

5

मुझे लगता है कि amon उसकी टिप्पणी में अपने प्रश्न का सबसे अच्छा शाब्दिक जवाब दिया: और अधिक स्पष्ट रूप

: स्ट्रिंग्स और regexes बचने के लिए अलग नियम होते हैं। एक स्ट्रिंग एक regex के स्थान पर इस्तेमाल किया जाता है, स्ट्रिंग शाब्दिक डबल बचने

मतलब है कि split '\\' एक स्ट्रिंग का उपयोग करता है और split /\\/ एक regex का उपयोग करता है से ग्रस्त हैं।

शायद आप एक मॉड्यूल बंटवारे रास्तों के लिए अनुकूल उपयोग करने पर विचार करना चाहिए:

एक व्यावहारिक जवाब के रूप में, मैं इस जोड़ना चाहते थे। File::Spec पर्ल 5 में एक कोर मॉड्यूल है। और साथ ही, आपको डबल कोटेड स्ट्रिंग में बैकस्लैश से बचना होगा, जिसे आपने नहीं किया है। आप सिंगल कोट्स का भी उपयोग कर सकते हैं, जो मेरी राय में थोड़ा बेहतर दिखता है।

use strict; 
use warnings; 
use Data::Dumper; 
use File::Spec; 

my $path = 'D:\Folder\AnotherFolder\file.txt'; # note the single quotes 
my @elements = File::Spec->splitdir($path); 
print Dumper \@elements; 

आउटपुट:

$VAR1 = [ 
      'D:', 
      'Folder', 
      'AnotherFolder', 
      'file.txt' 
     ]; 
+0

फ़ाइल :: स्पैक –

+0

@AndreiDoanca के साथ टिप के लिए धन्यवाद। विभाजन पथ के लिए सही उपकरण, और यह पोर्टेबल और भरोसेमंद है। मुझे यकीन नहीं है कि आप पथ को विभाजित करके क्या करने की कोशिश कर रहे हैं, लेकिन यह एक एक्सवाई-समस्या की तरह दिखता है। – TLP

+0

असल में यह एक्सवाई-समस्या नहीं है सिर्फ मेरी जिज्ञासा है :) –

2

neater तरीके एक पथ के तत्वों को निकालने के लिए में से एक वर्ण एक रास्ता सेपरेटर के अलावा अन्य के सभी दृश्यों को निकालने के लिए है।

use strict; 
use warnings; 

my $path = 'D:\Folder\AnotherFolder\file.txt'; 
my @path = $path =~ m([^/\\]+)g; 

print "$_\n" for @path; 

उत्पादन

D: 
Folder 
AnotherFolder 
file.txt 
2

जब splitsplit STRING के रूप में प्रयोग किया जाता है और न split REGEX, स्ट्रिंग एक regex में परिवर्तित कर दिया जा रहा है। आपके मामले में split '\\' को split /\/ में परिवर्तित कर दिया जाएगा क्योंकि पहली बैकस्लैश को बचने वाला चरित्र माना जाता है।

ऐसा करने का सही तरीका split '\\\\' है जिसका अनुवाद split /\\/ पर किया जाएगा।

+0

स्पष्टीकरण के लिए बहुत बहुत धन्यवाद, वास्तव में अच्छी जानकारी :) अब मैं समझता हूं और देखता हूं कि यह काम करता है :) –

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