Kabul edilen shlexyaklaşımla ilgili temel sorun, alıntı yapılan alt dizelerin dışındaki kaçış karakterlerini yok saymaması ve bazı köşe durumlarında biraz beklenmedik sonuçlar vermesidir.
Bu tür bir alt dize içinde tırnak kaçış yeteneği ile tek tırnaklı veya çift tırnaklı alt dizeleri korunur, giriş dizeleri böler bölünmüş bir işlev gereken aşağıdaki kullanım durumu var. Alıntılanmamış bir dize içindeki tırnak işaretleri diğer karakterlerden farklı olarak ele alınmamalıdır. Beklenen çıktıya sahip bazı örnek test örnekleri:
giriş dizesi | beklenen çıktı
===============================================
'abc def' | ['abc', 'def']
"abc \\ s def" | ['abc', '\\ s', 'def']
'"abc def" ghi' | ['abc def', 'ghi']
"'abc def' ghi" | ['abc def', 'ghi']
'"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']
'"" testi "| ['', 'Ölçek']
"'' testi" | ['', 'Ölçek']
"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"']
'abc "def" ghi' | ['abc "def",' ghi ']
'abc "def" ghi' | [ 'Abc "def" GSS']
"r'AA 'r'. * _ xyz $ '" | ["r'AA '", "r'. * _ xyz $ '"]
Bir dizeyi tüm çıktı dizeleri için beklenen çıktı sonuçları olacak şekilde bölmek için aşağıdaki işlevi ile sona erdi:
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)]
Aşağıdaki test uygulaması diğer yaklaşımların ( shlexve csvşimdilik) ve özel bölünmüş uygulamanın sonuçlarını kontrol eder :
#!/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)')
Çıktı:
shlex
[Tamam] abc def -> ['abc', 'def']
[FAIL] abc \ s def -> ['abc', 's', 'def']
[Tamam] "abc def" ghi -> ['abc def', 'ghi']
[Tamam] 'abc def' ghi -> ['abc def', 'ghi']
[Tamam] "abc \" def "ghi -> ['abc" def', 'ghi']
[FAIL] 'abc \' def 'ghi -> istisna: Kapanış teklifi yok
[Tamam] 'abc \ s def' ghi -> ['abc \\ s def', 'ghi']
[Tamam] "abc \ s def" ghi -> ['abc \\ s def', 'ghi']
[Tamam] "" test -> ['', 'test']
[Tamam] '' test -> ['', 'test']
[FAIL] abc'def -> istisna: Kapanış teklifi yok
[FAIL] abc'def '-> [' abcdef ']
[FAIL] abc'def 'ghi -> [' abcdef ',' ghi ']
[FAIL] abc'def'ghi -> ['abcdefghi']
[FAIL] abc "def -> istisna: Kapanış teklifi yok
[FAIL] abc "def" -> ['abcdef']
[FAIL] abc "def" ghi -> ['abcdef', 'ghi']
[FAIL] abc "def" ghi -> ['abcdefghi']
[BAŞARISIZ] r'AA 'r'. * _ Xyz $ '-> [' rAA ',' r. * _ Xyz $ ']
cSV
[Tamam] abc def -> ['abc', 'def']
[Tamam] abc \ s def -> ['abc', '\\ s', 'def']
[Tamam] "abc def" ghi -> ['abc def', 'ghi']
[FAIL] 'abc def' ghi -> ["'abc", "def'", 'ghi']
[FAIL] "abc \" def "ghi -> ['abc \\', 'def"', 'ghi']
[FAIL] 'abc \' def 'ghi -> ["' abc", "\\ '", "def'", 'ghi']
[FAIL] 'abc \ s def' ghi -> ["'abc",' \\ s ', "def'", 'ghi']
[Tamam] "abc \ s def" ghi -> ['abc \\ s def', 'ghi']
[Tamam] "" test -> ['', 'test']
[FAIL] '' test -> ["''", 'test']
[Tamam] abc'def -> ["abc'def"]
[Tamam] abc'def '-> ["abc'def'"]
[Tamam] abc'def 'ghi -> ["abc'def'", 'ghi']
[Tamam] abc'def'ghi -> ["abc'def'ghi"]
[Tamam] abc "def -> ['abc" def']
[Tamam] abc "def" -> ['abc "def"']
[Tamam] abc "def" ghi -> ['abc "def"', 'ghi']
[Tamam] abc "def" ghi -> ['abc "def" ghi']
[Tamam] r'AA 'r'. * _ Xyz $ '-> ["r'AA'", "r '. * _ Xyz $'"]
yeniden
[Tamam] abc def -> ['abc', 'def']
[Tamam] abc \ s def -> ['abc', '\\ s', 'def']
[Tamam] "abc def" ghi -> ['abc def', 'ghi']
[Tamam] 'abc def' ghi -> ['abc def', 'ghi']
[Tamam] "abc \" def "ghi -> ['abc" def', 'ghi']
[Tamam] 'abc \' def 'ghi -> ["abc' def", 'ghi']
[Tamam] 'abc \ s def' ghi -> ['abc \\ s def', 'ghi']
[Tamam] "abc \ s def" ghi -> ['abc \\ s def', 'ghi']
[Tamam] "" test -> ['', 'test']
[Tamam] '' test -> ['', 'test']
[Tamam] abc'def -> ["abc'def"]
[Tamam] abc'def '-> ["abc'def'"]
[Tamam] abc'def 'ghi -> ["abc'def'", 'ghi']
[Tamam] abc'def'ghi -> ["abc'def'ghi"]
[Tamam] abc "def -> ['abc" def']
[Tamam] abc "def" -> ['abc "def"']
[Tamam] abc "def" ghi -> ['abc "def"', 'ghi']
[Tamam] abc "def" ghi -> ['abc "def" ghi']
[Tamam] r'AA 'r'. * _ Xyz $ '-> ["r'AA'", "r '. * _ Xyz $'"]
shlex: yineleme başına 0.281 ms
csv: yineleme başına 0,030 ms
re: yineleme başına 0.049 ms
Bu nedenle performans, shlexnormal ifadeden önceden derlenerek daha iyi olur ve bu durumda csvyaklaşımdan daha iyi performans gösterir .