続:「bogus」をエミュレートしたければ皿まで (shell32.CommandLineToArgvW)

「ダメダ」はやっぱしダメだった…。

ここで言っている「回答者」は正しい。

本物の「バカ」完全互換じゃないのな…。検証用バッチ:

aaa.bat
1 @echo %1
2 @echo %2
3 @echo %3

やってみる:

1 c:\do\me\s\to\s> aaa.bat ""  aaa"bbb""" ccc
2 ""
3 aaa"bbb"""
4 ccc

CommandLineToArgvW は「正しいバカ」になりきれておらず、「バカの変種」を新たに生み出しただけ。

ちょっと回答者のコードが今のワタシの目的には過汎用なので単純化すると:

 1 import re
 2 def cmdline_split(s):
 3     RE_CMD_LEX = r'''"((?:""|\\["\\]|[^"])*)"?()|(\\\\(?=\\*")|\\")|(&&?|\|\|?|\d?>|[<])|([^\s"&|<>]+)|(\s+)|(.)'''
 4 
 5     args = []
 6     accu = None   # collects pieces of one arg
 7     for qs, qss, esc, pipe, word, white, fail in re.findall(RE_CMD_LEX, s):
 8         if word:
 9             pass   # most frequent
10         elif esc:
11             word = esc[1]
12         elif white or pipe:
13             if accu is not None:
14                 args.append(accu)
15             if pipe:
16                 args.append(pipe)
17             accu = None
18             continue
19         elif fail:
20             raise ValueError("invalid or incomplete shell string")
21         elif qs:
22             word = qs.replace('\\"', '"').replace('\\\\', '\\')
23             word = word.replace('""', '"')
24         else:
25             word = qss   # may be even empty; must be last
26 
27         accu = (accu or '') + word
28 
29     if accu is not None:
30         args.append(accu)
31 
32     return args

となるが、これだと確かに「バカ互換」になる。(無論「囲んでいる引用符まで垂れ流されてくる」のを剥がす差異は見かけ上出る。)

一つ前の記事で「DOS パーサに近しいご用を足せるもの」はこっちをベースに書こう…。