स्वीकृत shlexदृष्टिकोण के साथ मुख्य समस्या यह है कि उद्धृत उद्धरणों के बाहर भागने वाले पात्रों को अनदेखा नहीं करता है, और कुछ कोने के मामलों में थोड़ा अप्रत्याशित परिणाम देता है।
मेरे पास निम्नलिखित उपयोग का मामला है, जहां मुझे एक विभाजन फ़ंक्शन की आवश्यकता होती है जो इनपुट स्ट्रिंग्स को विभाजित करता है जैसे कि या तो एकल-उद्धृत या दोहरे-उद्धरण वाले सब्सट्रेटिंग संरक्षित हैं, ऐसे विकल्प के भीतर उद्धरण से बचने की क्षमता है। एक निर्विवाद स्ट्रिंग के भीतर उद्धरण किसी अन्य चरित्र से अलग तरह से व्यवहार नहीं किया जाना चाहिए। अपेक्षित उत्पादन के साथ कुछ उदाहरण परीक्षण मामले:
इनपुट स्ट्रिंग | अपेक्षित उत्पादन
===============================================
'abc def' | ['abc', 'def']
"abc \\ s def" | ['abc', '\\ s', 'def']
'' '' एबीसी दे '' घी '' | ['abc def', 'ghi']
"" एबीसी डीई 'जी "| ['abc def', 'ghi']
"" एबीसी \\ "डिफ" गि "। ['एबीसी" डीईएफ़,' गि '']
"" abc \\ 'def' ghi "| ["abc 'def",' ghi ']
"" abc \\ s def 'ghi "| ['abc \\ s def', 'ghi']
"" abc \\ s def "ghi" | ['abc \\ s def', 'ghi']
'' '' परीक्षण '' | ['', 'परीक्षा']
"" 'परीक्षण "| ['', 'परीक्षा']
"abc'def" | [ "Abc'def"]
"abc'def '" | [ "Abc'def '"]
"abc'def 'ghi" | ["abc'def" ", 'घी']
"abc'def'ghi" | [ "Abc'def'ghi"]
"एबीसी" डीईएफ़।] ['एबीसी' डीफ़ ']
"एबीसी" डीफ़ "" | [ 'एबीसी "def"']
g abc ”def“ घी ’| ['abc "def",' ghi ']
g abc ”def“ घी ’| [ 'एबीसी "def" GHI']
"r'AA 'r'। * _ xyz $ '" | ["r'AA '", "r'। * _ xyz $ '"]
मैंने निम्नलिखित फ़ंक्शन के साथ एक स्ट्रिंग को विभाजित करने के लिए समाप्त किया, ताकि सभी इनपुट स्ट्रिंग के लिए अपेक्षित आउटपुट परिणाम मिलें:
import re
def quoted_split(s):
def strip_quotes(s):
if s and (s[0] == '"' or s[0] == "'") and s[0] == s[-1]:
return s[1:-1]
return s
return [strip_quotes(p).replace('\\"', '"').replace("\\'", "'") \
for p in re.findall(r'"(?:\\.|[^"])*"|\'(?:\\.|[^\'])*\'|[^\s]+', s)]
निम्नलिखित परीक्षण एप्लिकेशन अन्य दृष्टिकोणों ( shlexऔर csvअभी के लिए) और कस्टम विभाजन कार्यान्वयन के परिणामों की जांच करता है :
#!/bin/python2.7
import csv
import re
import shlex
from timeit import timeit
def test_case(fn, s, expected):
try:
if fn(s) == expected:
print '[ OK ] %s -> %s' % (s, fn(s))
else:
print '[FAIL] %s -> %s' % (s, fn(s))
except Exception as e:
print '[FAIL] %s -> exception: %s' % (s, e)
def test_case_no_output(fn, s, expected):
try:
fn(s)
except:
pass
def test_split(fn, test_case_fn=test_case):
test_case_fn(fn, 'abc def', ['abc', 'def'])
test_case_fn(fn, "abc \\s def", ['abc', '\\s', 'def'])
test_case_fn(fn, '"abc def" ghi', ['abc def', 'ghi'])
test_case_fn(fn, "'abc def' ghi", ['abc def', 'ghi'])
test_case_fn(fn, '"abc \\" def" ghi', ['abc " def', 'ghi'])
test_case_fn(fn, "'abc \\' def' ghi", ["abc ' def", 'ghi'])
test_case_fn(fn, "'abc \\s def' ghi", ['abc \\s def', 'ghi'])
test_case_fn(fn, '"abc \\s def" ghi', ['abc \\s def', 'ghi'])
test_case_fn(fn, '"" test', ['', 'test'])
test_case_fn(fn, "'' test", ['', 'test'])
test_case_fn(fn, "abc'def", ["abc'def"])
test_case_fn(fn, "abc'def'", ["abc'def'"])
test_case_fn(fn, "abc'def' ghi", ["abc'def'", 'ghi'])
test_case_fn(fn, "abc'def'ghi", ["abc'def'ghi"])
test_case_fn(fn, 'abc"def', ['abc"def'])
test_case_fn(fn, 'abc"def"', ['abc"def"'])
test_case_fn(fn, 'abc"def" ghi', ['abc"def"', 'ghi'])
test_case_fn(fn, 'abc"def"ghi', ['abc"def"ghi'])
test_case_fn(fn, "r'AA' r'.*_xyz$'", ["r'AA'", "r'.*_xyz$'"])
def csv_split(s):
return list(csv.reader([s], delimiter=' '))[0]
def re_split(s):
def strip_quotes(s):
if s and (s[0] == '"' or s[0] == "'") and s[0] == s[-1]:
return s[1:-1]
return s
return [strip_quotes(p).replace('\\"', '"').replace("\\'", "'") for p in re.findall(r'"(?:\\.|[^"])*"|\'(?:\\.|[^\'])*\'|[^\s]+', s)]
if __name__ == '__main__':
print 'shlex\n'
test_split(shlex.split)
print
print 'csv\n'
test_split(csv_split)
print
print 're\n'
test_split(re_split)
print
iterations = 100
setup = 'from __main__ import test_split, test_case_no_output, csv_split, re_split\nimport shlex, re'
def benchmark(method, code):
print '%s: %.3fms per iteration' % (method, (1000 * timeit(code, setup=setup, number=iterations) / iterations))
benchmark('shlex', 'test_split(shlex.split, test_case_no_output)')
benchmark('csv', 'test_split(csv_split, test_case_no_output)')
benchmark('re', 'test_split(re_split, test_case_no_output)')
आउटपुट:
shlex
[ठीक है] abc def -> ['abc', 'def']
[विफल] abc \ s def -> ['abc', 's', 'def']
[ठीक है] "abc def" ghi -> ['abc def', 'ghi']
[ठीक है] 'एबीसी डीईए' गि -> ['एबीसी डीएफ ’,' जीआईएच]
[ठीक है] "abc \" को "ghi -> [" abc "को परिभाषित करें, 'ghi']
[विफल] 'abc \' def 'ghi -> अपवाद: कोई समापन उद्धरण नहीं
[ठीक है] 'abc \ s def' ghi -> ['abc \\ s def', 'ghi']
[ठीक है] "abc \ s def" ghi -> ['abc \\ s def', 'ghi']
[ठीक] "" परीक्षण -> ['', 'परीक्षण']
[ठीक है] '' परीक्षण -> ['', 'परीक्षण']
[विफल] abc'def -> अपवाद: कोई समापन उद्धरण नहीं
[विफल] abc'def '-> [' abcdef ']
[FAIL] abc'def 'ghi -> [' abcdef ',' ghi ']
[विफल] abc'def'ghi -> ['abcdefghi']
[विफल] abc "def -> अपवाद: कोई समापन उद्धरण नहीं
[FAIL] abc "def" -> ['abcdef']
[FAIL] abc "def" ghi -> ['abcdef', 'ghi']
[FAIL] abc "def" ghi -> ['abcdefghi']
[FAIL] r'AA 'r'। * _ Xyz $ '-> [' rAA ',' r। * _ Xyz $ ']
सीएसवी
[ठीक है] abc def -> ['abc', 'def']
[ठीक] abc \ s def -> ['abc', '\\ s', 'def']
[ठीक है] "abc def" ghi -> ['abc def', 'ghi']
[FAIL] 'abc def' ghi -> ["abc", "def '",' ghi ']
[FAIL] "abc \" def "ghi -> ['abc \\', 'def"','hi ']
[FAIL] 'abc \' def 'ghi -> ["" abc "," \\' "," def '",' ghi ']
[विफल] 'abc \ s def' ghi -> ["abc", '\\ s', "def '",' ghi ']
[ठीक है] "abc \ s def" ghi -> ['abc \\ s def', 'ghi']
[ठीक] "" परीक्षण -> ['', 'परीक्षण']
[विफल] '' परीक्षण -> ["" "," परीक्षण ']
[ठीक है] abc'def -> ["abc'def"]
[ठीक है] abc'def '-> ["abc'def'"]
[ठीक है] abc'def 'ghi -> ["abc'def" ",' ghi ']
[ठीक है] abc'def'ghi -> ["abc'def'ghi"
[ठीक है] abc "def -> ['abc" def']
[ठीक] abc "def" -> ['abc "def"']
[ओके] एबीसी "डीईई" गि -> ['एबीसी "डीफ़" "," जीआईएच]]
[ठीक है] एबीसी "डीईई" गि -> [एबीसी "डीईएटी" जीआईएच]]
[ठीक है] r'AA 'r'। * _ xyz $ '-> ["r'AA'", "r '। * _ xyz $'"]
फिर से
[ठीक है] abc def -> ['abc', 'def']
[ठीक] abc \ s def -> ['abc', '\\ s', 'def']
[ठीक है] "abc def" ghi -> ['abc def', 'ghi']
[ठीक है] 'एबीसी डीईए' गि -> ['एबीसी डीएफ ’,' जीआईएच]
[ठीक है] "abc \" को "ghi -> [" abc "को परिभाषित करें, 'ghi']
[ठीक है] 'abc \' def 'ghi -> ["abc' def", 'ghi']
[ठीक है] 'abc \ s def' ghi -> ['abc \\ s def', 'ghi']
[ठीक है] "abc \ s def" ghi -> ['abc \\ s def', 'ghi']
[ठीक] "" परीक्षण -> ['', 'परीक्षण']
[ठीक है] '' परीक्षण -> ['', 'परीक्षण']
[ठीक है] abc'def -> ["abc'def"]
[ठीक है] abc'def '-> ["abc'def'"]
[ठीक है] abc'def 'ghi -> ["abc'def" ",' ghi ']
[ठीक है] abc'def'ghi -> ["abc'def'ghi"
[ठीक है] abc "def -> ['abc" def']
[ठीक] abc "def" -> ['abc "def"']
[ओके] एबीसी "डीईई" गि -> ['एबीसी "डीफ़" "," जीआईएच]]
[ठीक है] एबीसी "डीईई" गि -> [एबीसी "डीईएटी" जीआईएच]]
[ठीक है] r'AA 'r'। * _ xyz $ '-> ["r'AA'", "r '। * _ xyz $'"]
श्लेक्स: 0.281ms प्रति पुनरावृत्ति
सीएसवी: बग्स प्रति पुनरावृत्ति
पुन: 0.049ms प्रति पुनरावृत्ति
इसलिए प्रदर्शन की तुलना में बहुत बेहतर है shlex, और नियमित अभिव्यक्ति को आगे बढ़ाकर सुधार किया जा सकता है, इस मामले में यह csvदृष्टिकोण को बेहतर बना देगा ।