पायथन के कच्चे तार के शाब्दिक एकल बैकस्लैश के साथ समाप्त क्यों नहीं हो सकते?


179

तकनीकी रूप से, बैकस्लैश की कोई भी विषम संख्या, जैसा कि प्रलेखन में वर्णित है ।

>>> r'\'
  File "<stdin>", line 1
    r'\'
       ^
SyntaxError: EOL while scanning string literal
>>> r'\\'
'\\\\'
>>> r'\\\'
  File "<stdin>", line 1
    r'\\\'
         ^
SyntaxError: EOL while scanning string literal

ऐसा लगता है कि पार्सर कच्चे तार में बैकस्लैश का इलाज नियमित पात्रों के रूप में कर सकता है (यह नहीं है कि कच्चे तार सभी के बारे में क्या हैं?), लेकिन मैं शायद कुछ स्पष्ट याद कर रहा हूं।


8
ऐसा लगता है कि अब यह एक faq है । हो सकता है कि जब आप सवाल न पूछें। मुझे पता है कि आपके द्वारा बताए गए दस्तावेज़ बहुत अधिक समान हैं, लेकिन मुझे लगा कि मैं प्रलेखन का दूसरा स्रोत जोड़ूंगा।
oob

जवाबों:


124

कारण उस अनुभाग के भाग में बताया गया है जिसे मैंने बोल्ड में हाइलाइट किया था:

स्ट्रिंग उद्धरण एक बैकस्लैश के साथ बच सकते हैं, लेकिन बैकस्लैश स्ट्रिंग में रहता है; उदाहरण के लिए, r"\""दो पात्रों से मिलकर एक मान्य स्ट्रिंग शाब्दिक है: एक बैकस्लैश और एक डबल उद्धरण; r"\"एक वैध स्ट्रिंग शाब्दिक नहीं है (यहां तक ​​कि एक कच्ची स्ट्रिंग विषम संख्या में वापस नहीं हो सकती है)। विशेष रूप से, एक कच्चा स्ट्रिंग एक एकल बैकस्लैश में समाप्त नहीं हो सकता (क्योंकि बैकस्लैश निम्नलिखित उद्धरण वर्ण से बच जाएगा)। यह भी ध्यान दें कि एक नई रूपरेखा के बाद एक एकल बैकस्लैश की व्याख्या स्ट्रिंग के भाग के रूप में उन दो वर्णों के रूप में की जाती है, न कि एक पंक्ति निरंतरता के रूप में।

तो कच्चे तार 100% कच्चे नहीं हैं, अभी भी कुछ अल्पविकसित बैकलैश-प्रसंस्करण है।


21
अरे वाह ... यह अजीब है। अच्छा पकड़ा। समझ में आता है कि r '\' '== "\\'" लेकिन यह अभी भी अजीब है कि भागने के चरित्र को गायब किए बिना एक प्रभाव है।
cdleary

2
@ विजावर यह फ़ाइल सिस्टम पथ के लिए काम कर सकता है, लेकिन बैकस्लैश के अन्य उपयोग हैं। और फ़ाइल सिस्टम पथ के लिए, विभाजक को हार्डकोड न करें। 'Os.path.sep' का उपयोग करें, या 'os.path' की उच्च स्तरीय विशेषताओं का बेहतर उपयोग करें। (या 'पथलिब', जब उपलब्ध हो)
20

5
नोट: वर्कअराउंड आसन्न शाब्दिक सहमति का उपयोग करना है। r"foo\bar\baz" "\\"(परगनों में लपेटो अगर अस्पष्ट) संकलन समय पर एक एकल शाब्दिक पैदा करेगा, जिसमें से पहला हिस्सा कच्चा है, और केवल आखिरी छोटा सा गैर-कच्चा है, जो पीछे की ओर पीछे हटने की अनुमति देता है।
शैडो रेंजर

2
IMO यह सिर्फ यह बताता है कि प्रश्न (क्या अनुमति है / काम करेगा, और क्या नहीं), बिना यह कहे कि यह इस तरह से क्यों बनाया गया है। एक FAQ प्रविष्टि है जो बताती है कि क्यों (कच्चे तार एक विशिष्ट उद्देश्य के लिए डिज़ाइन किए गए थे, और यह उस उद्देश्य के संदर्भ में समझ में आता है)।
श्रीवत्सआर

3
फिर कच्चे तार की क्या बात है? अवधारणा की एक छायादार कार्यान्वयन की तरह लगता है।
मैथ्यू जेम्स ब्रिग्स

101

अजगर के कच्चे तारों के बारे में पूरी गलत धारणा यह है कि ज्यादातर लोग सोचते हैं कि बैकस्लैश (एक कच्चे स्ट्रिंग के भीतर) अन्य सभी लोगों की तरह एक नियमित चरित्र है। यह नहीं। इस अजगर के ट्यूटोरियल अनुक्रम को समझने की कुंजी है:

जब कोई ' r ' या ' R ' उपसर्ग मौजूद होता है, तो बैकस्लैश का अनुसरण करने वाला वर्ण बिना परिवर्तन के स्ट्रिंग में शामिल हो जाता है, और सभी बैकस्लैश स्ट्रिंग में रह जाते हैं

बैकस्लैश का अनुसरण करने वाला कोई भी चरित्र कच्चे स्ट्रिंग का हिस्सा है। एक बार पार्सर एक कच्चे स्ट्रिंग (गैर यूनिकोड एक) में प्रवेश करता है और एक बैकस्लैश का सामना करता है यह जानता है कि 2 वर्ण (एक बैकस्लैश और इसके बाद एक चर) हैं।

इस तरफ:

r'abc \ d ' में a, b, c, \, d शामिल हैं

r'abc \ 'प' में a, b, c, \, ', d शामिल हैं

r'abc \ '' में a, b, c, \,' शामिल हैं

तथा:

r'abc \ ' में a, b, c, \, शामिल हैं लेकिन अब कोई समाप्ति उद्धरण नहीं है।

अंतिम मामला दिखाता है कि अब दस्तावेज़ के अनुसार एक पार्सर को क्लोजिंग उद्धरण नहीं मिल सकता है क्योंकि आप जो अंतिम उद्धरण देख रहे हैं वह स्ट्रिंग का हिस्सा है यानी बैकस्लैश यहाँ अंतिम नहीं हो सकता है क्योंकि यह स्ट्रिंग को 'डेवॉर' करेगा।


8
यह वास्तव में स्वीकृत उत्तर की तुलना में स्पष्ट है। अच्छा टूटना।
मैड

4
मुझे भी स्वीकृत उत्तर की तुलना में यह काफी स्पष्ट लगता है, और मैं एक भौतिक विज्ञानी होने के लिए भी हूं
xdavidliu

22

ऐसा ही है! मैं इसे अजगर में उन छोटे दोषों में से एक के रूप में देखता हूं!

मुझे नहीं लगता कि इसके लिए एक अच्छा कारण है, लेकिन यह निश्चित रूप से नहीं है; यह एक अंतिम चरित्र के रूप में कच्चे तार को पार्स करने के लिए वास्तव में आसान है।

यह पकड़ है, यदि आप एक कच्चे तार में अंतिम वर्ण होने की अनुमति देते हैं, तो आप "एक कच्चे स्ट्रिंग के अंदर" नहीं डाल पाएंगे। ऐसा लगता है कि अजगर अंतिम चरित्र के रूप में अनुमति देने के बजाय "अनुमति देने" के साथ गया था।

हालाँकि, इससे कोई परेशानी नहीं होनी चाहिए।

यदि आप आसानी से विंडोज़ फ़ोल्डर पथ लिखने में सक्षम नहीं होने के बारे में चिंतित हैं c:\mypath\, तो चिंता न करें, इसके लिए, आप उन्हें इस रूप में दर्शा सकते हैं r"C:\mypath", और, यदि आपको एक उपनिर्देशिका नाम संलग्न करने की आवश्यकता है, तो इसे स्ट्रिंग के साथ नहीं करें, के लिए यह वैसे भी ऐसा करने का सही तरीका नहीं है! उपयोगos.path.join

>>> import os
>>> os.path.join(r"C:\mypath", "subfolder")
'C:\\mypath\\subfolder'

2
अच्छा सहायक सामग्री। :-) शैतान का वकील, हालाँकि: कभी-कभी आप पथ विभाजक को जोड़कर निर्देशिका पथ से फ़ाइल पथ को अलग करना चाहते हैं। Os.path.join के बारे में अच्छी बात यह है कि यह उन्हें ढहा देगा: As.path.join ('/ home / cdleary /', 'foo /', 'bar /') == '' / home / ddleary / foo / बार / '
cdleary

हालांकि यह (तकनीकी) अंतर नहीं करता है! os.path.isdir आपको बताएगा कि क्या कोई निश्चित पथ एक निर्देशिका (फ़ोल्डर) है
has

2
हां, यह केवल कोड पढ़ने वाले किसी व्यक्ति को इंगित करना है कि क्या आप एक निर्देशिका या एक फ़ाइल होने की उम्मीद करते हैं।
cdleary

खिड़कियों पर कन्वेंशन यह है कि फाइलों में एक एक्सटेंशन होता है, हमेशा। यह संभव नहीं है (सामान्य परिस्थितियों में) सी: \ path \ data
has

5
..और आप उन्हें "c: / mypath" के रूप में प्रस्तुत कर सकते हैं और अपने बैकस्लैश के संकटों को पूरी तरह से भूल जाएंगे :-)
जॉन फूही

14

एक स्लैश के साथ एक कच्चे तार को समाप्त करने के लिए मैं आपको सुझाव देता हूं कि आप इस ट्रिक का उपयोग कर सकते हैं:

>>> print r"c:\test"'\\'
test\

14

एक और चाल chr (92) का उपयोग करना है क्योंकि यह "\" का मूल्यांकन करता है।

मुझे हाल ही में बैकस्लैश की एक स्ट्रिंग को साफ करना था और निम्नलिखित ने चाल चली:

CleanString = DirtyString.replace(chr(92),'')

मुझे पता है कि यह "क्यों" का ख्याल नहीं रखता है, लेकिन धागा तत्काल समस्या का समाधान ढूंढ रहे कई लोगों को आकर्षित करता है।


लेकिन क्या होगा अगर मूल स्ट्रिंग में बैकस्लैश शामिल हैं?
जोसेफ रेडनर


9

चूंकि कच्चे स्ट्रिंग के अंदर \ "की अनुमति है। तब इसे स्ट्रिंग शाब्दिक के अंत की पहचान करने के लिए इस्तेमाल नहीं किया जा सकता है।

जब आप पहली बार मुठभेड़ करते हैं तो स्ट्रिंग शाब्दिक को पार्स करना बंद क्यों नहीं करते हैं?

अगर ऐसा था, तो स्ट्रिंग शाब्दिक के अंदर अनुमति नहीं दी जाएगी। लेकिन यह है।


1
बिल्कुल सही। पायथन डिजाइनरों ने संभवतः दो विकल्पों की संभावना का मूल्यांकन किया है: दो-चरित्र अनुक्रम \"कहीं भी एक डबल-उद्धृत कच्चे स्ट्रिंग के भीतर, या डबल-उद्धृत कच्चे स्ट्रिंग के अंत में। उपयोग के आँकड़ों के अंत में कहीं भी दो-वर्ण अनुक्रम का पक्ष लेना चाहिए।
होब्स

3

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

लेकिन आप उपयोग कर सकते हैं:

'\\'

4
जवाब नहीं 'क्यों' :-)
cdleary

2

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

मुझे लगा कि यह एक दिलचस्प विचार है और इसे पोस्टीरिटी के लिए सामुदायिक विकि के रूप में शामिल किया गया है।


लेकिन यह आपको दो अलग-अलग स्ट्रिंग-शाब्दिक-पार्सर कोड पथ से बचने की अनुमति दे सकता है।
cdleary

2

अपनी भूमिका के बावजूद, यहां तक ​​कि एक कच्ची स्ट्रिंग एक भी बैकस्लैश में समाप्त नहीं हो सकती, क्योंकि बैकस्लैश निम्नलिखित उद्धरण चरित्र से बच जाता है - आपको अभी भी इसे स्ट्रिंग में एम्बेड करने के लिए आसपास के उद्धरण चरित्र से बचना चाहिए। यही है, r "... \" एक वैध स्ट्रिंग शाब्दिक नहीं है - एक कच्ची स्ट्रिंग बैकस्लैश की एक विषम संख्या में समाप्त नहीं हो सकती है।
यदि आपको एक एकल बैकस्लैश के साथ एक कच्ची स्ट्रिंग को समाप्त करने की आवश्यकता है, तो आप दो का उपयोग कर सकते हैं और दूसरे से स्लाइस कर सकते हैं।


1

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

यह वास्तव में \ N को अंतिम चरित्र के रूप में अस्वीकार करता है क्योंकि यह "से बच जाएगा" और पार्सर को चोक कर देगा। लेकिन जैसा कि पहले बताया गया है कानूनी है।


1
हाँ - इस मुद्दे का दिल यह था कि कच्चे तार एक भागने के क्रम की शुरुआत के बजाय एक शाब्दिक के रूप में व्यवहार करते हैं। अजीब बात यह है कि यह अभी भी शाब्दिक चरित्र के रूप में व्यवहार किए जाने के बावजूद, उद्धरण के लिए गुणों से बच गया है।
cdleary

1

कुछ सुझाव :

1) यदि आपको पथ के लिए बैकस्लैश में हेरफेर करने की आवश्यकता है तो मानक अजगर मॉड्यूल os.path आपका मित्र है। उदाहरण के लिए :

os.path.normpath ( 'c: / फ़ोल्डर 1 /')

2) यदि आप इसमें स्ट्रिंग का निर्माण करना चाहते हैं तो BUT बिना बैकस्लैश के अपने स्ट्रिंग के अंत में कर सकते हैं तो कच्ची स्ट्रिंग आपका दोस्त है (आपके शाब्दिक स्ट्रिंग से पहले 'r' उपसर्ग का उपयोग करें)। उदाहरण के लिए :

r'\one \two \three'

3) यदि आपको बैकस्लैश के साथ चर X में एक स्ट्रिंग को उपसर्ग करने की आवश्यकता है, तो आप ऐसा कर सकते हैं:

X='dummy'
bs=r'\ ' # don't forget the space after backslash or you will get EOL error
X2=bs[0]+X  # X2 now contains \dummy

4) यदि आपको अंत में एक बैकस्लैश के साथ एक स्ट्रिंग बनाने की आवश्यकता है, तो टिप 2 और 3 को मिलाएं:

voice_name='upper'
lilypond_display=r'\DisplayLilyMusic \ ' # don't forget the space at the end
lilypond_statement=lilypond_display[:-1]+voice_name

अब lilypond_statement में शामिल है "\DisplayLilyMusic \upper"

लंबे समय तक जीवित अजगर! :)

n3on


1
इनमें से कोई भी "क्यों" के प्रश्न का उत्तर नहीं देता है, लेकिन # 3 और # 4 का उपयोग नहीं किया जाना चाहिए। स्लाइसिंग और स्ट्रिंग्स को जोड़ना आम तौर पर बुरा अभ्यास है, और आपको # 3 (जो ठीक काम करता है) और '.join ([r' \ \ DisplayLilyMusic ', r' \ ऊपरी ']) से # 4 के लिए r' डमी 'पसंद करना चाहिए।
cdleary

1
कारण यह है कि तार अपरिवर्तनीय हैं और प्रत्येक स्लाइस / कॉनटेनैशन एक नई अपरिवर्तनीय स्ट्रिंग ऑब्जेक्ट बनाता है जिसे आमतौर पर त्याग दिया जाता है। उन सभी को संचय करने और str.join (घटकों) के साथ एक कदम में एक साथ जुड़ने के लिए बेहतर है
cdleary

ओह, वूप्स - गलत समझा कि तुम # 3 के लिए क्या मतलब था। मुझे लगता है कि एक साधारण '\\' + एक्स को केवल एक टुकड़ा बनाने के लिए पसंद किया जाता है।
cdleary 22

बस पाओगे os.path.normpathटेलिंग बैकस्लैश को हटा दो ... फिर मैं रास्ते में फ़ाइल नाम कैसे छुपाऊं ...
जिंग He

0

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

x = 'a string\\' 
x
'a string\\' 

# Now save it in a text file and it will appear with a single backslash:

with open("my_file.txt", 'w') as h:
    h.write(x)

BTW यह json के साथ काम नहीं कर रहा है यदि आप इसे अजगर के json लाइब्रेरी का उपयोग करके डंप करते हैं।

अंत में, मैं स्पाइडर के साथ काम करता हूं, और मैंने देखा कि अगर मैं स्पाइडर के टेक्स्ट एडिटर में वेरिएबल को वेरिएबल एक्सप्लोरर में उसके नाम पर डबल क्लिक करके खोलता हूं, तो इसे एक सिंगल बैकलैश के साथ प्रस्तुत किया जाता है और इसे क्लिपबोर्ड पर कॉपी किया जा सकता है (यह नहीं है) बहुत जरूरतों के लिए बहुत उपयोगी है लेकिन शायद कुछ के लिए ..)।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.