//cmdline 命令行参数解析 import process; namespace string; class cmdline{ ctor( s ){ if( ( type(s) != "string") || ( !#s ) ) return null; var p,argc = ::Shell32.CommandLineToArgvP(s,{int v}); if(p){ var argv = ..raw.convertArray(p,argc.v,"ustring"); if(#argv)argv[0] = ..table.shift(argv); ::Kernel32.LocalFree(pArgv); argv@ = _meta; return argv; } return null; /*不调用API实现{{*/ /* var cur = {}; var push = ..table.push; var a,b = ..string.match(s,s[1] == '"'# ? '"([^"]+)"(.*)' : '(\\S*)(.*)') this[0] = #a ? { ..string.unpack(a) } : {} ; s = b; var len = #s; for (i=1;len) { var c = s[i]; if (c === '"'#) { while(i<=len){ i++; var c = s[i]; if( c == '"'# ){ if( s[i+1] == '"'# ){ push(cur,c); i++; } break; //关闭引用 } elseif( c == '\\'# ){ var b,q = ..string.match( s,"(\\+)(""?)",i); i = i + ( #b - 1 ); if( !#q ){ push(cur,..string.unpack(b) ); continue; } for(k=1;#b/2 ){ push( cur,'\\'#) }; if( #b % 2 ){ push( cur,'"'#) i++; } } else { push(cur,c) } } continue ; //考虑""" } if( c === ' '# || c = '\t'# ){ if(#cur){ push( this,cur ) cur = {}; } } elseif( c == '\\'# ){ var b,q = ..string.match( s,"(\\+)(""?)",i); i = i + ( #b - 1 ); if( !#q ){ push(cur,..string.unpack(b) ); continue; } for(k=1;#b/2 ){ push( cur,'\\'#) } if( #b % 2 ){ push( cur,'"'#) i++; } continue; } else { push(cur,c); } } if(#cur)push( this,cur ); for(k,v in this) this[k] = ..string.pack(v); */ /*}}*/ }; } cmdline._meta = { _tostring = function(){ var s = ..process.joinArguments(owner); if( !owner[0] ) s = " " + s; return s; } } cmdline.arguments = function(param,...){ if(!param)return {}; if(type(param)==="table") return param,...; param = ..string.trim(param); if( (!...) && ..string.find(param,"\s+")){ if( param[1] != '"'# || param[#v] != '"'# ){ var p = ..string.cmdline(" " + param ); p[0] = null; return p; } } return {param;...} } cmdline.argv = function(str){ var r = cmdline(str); var n1,n2; var p1,p2; var sp; for(i=1;#r){ n2 = r[i]; p2 = n2[1] sp = ..string.indexAny(n2,' \t\r\n\'"{}[]()'); if(n1 && ((p2!=p1) || sp) ) r[n1] = n2; elseif( (p2=='-'# || p2=='/'#) ){ n2 = ..string.trimleft(n2,n2[[1]]); var k,v = ..string.match(n2,"(.+?)\=(.+)"); if(k && v){ r[k] = v; } else{ r[n2] = "" n1 = n2; p1 = p2; continue; } } n1 = null; p1 = null; } return r; } /**intellisense() string.cmdline = 解析命令行参数\n生成命令行参数请使用 string.args 。 string.cmdline( = 解析命令行,返回数组\n该数组可修改后调用 tostring 函数反解析为字符串文本\n参数不是字符串、或为空串返回 null string.cmdline(.("命令行") = 所有【参数段】以空格或制表等分开\n在一对双引号中表示的【引用段】则可以包含空格\n两个连续的引号表示一个引号字符并且关闭【引用段】\n关闭【引用段】后的非空格字符或引用段仍然追加其后\n\n一个或多个连续的反斜杠如果最后有一个引号则启用转义\n单个反斜杠转义其后的引号或反斜杠表示字面值\n\n首个索引为0的参数段要么是引号包含的引用段,或是任意非空白字符组成 string.cmdline.arguments( = 解析并转换创建进程的命令行参数 string.cmdline.arguments(.(命令行参数->->->) = 解析并转换创建进程的命令行参数,\n将一个或多个命令行参数转换为数组,\n如果参数@1是一个表,则直接返回所有参数,\n如只有一个文本参数且含空格、首尾无双引号则解析并返回数组,\n否则直接将所有参数置入数组返回,\n\n返回数组不包含索引为0的启动程序路径,\n返回数组可传入 process.joinArguments 函数 或 process 构造函数作为参数 string.cmdline.argv( = 调用 string.cmdline 解析命令行参数并返回数组,\n该数组也包含按下列规则解析的名值对:\n以斜杠或短横线开始的前导参数作为键(键名移除一个或多个相同的前导字符,区分大小写),\n如果前导参数包含等号,则以等号拆分为键值对,等号前后不应有空格,\n否则检查下一参数如果没有相同的首字符则设为此键对应的值,\n如果一个前导参数没有指定值,则默认值为空字符串(逻辑值为true)。\n注意参数名区分大小写 string.cmdline.argv(.("命令行") = 调用 string.cmdline 解析命令行参数并返回数组,\n该数组也包含解析后的名值对。\n\n解析名值对时忽略索引为0的参数,\n首个索引为0的参数段要么是引号包含的引用段,或是任意非空白字符组成,\n命令行以空白字符开始表示索引为 0 的参数为空 string.cmdline.argv() = !stringCmdlineArgv. !stringCmdlineArgv.? = 请输入命令行参数中以斜杠或短横线开始的前导参数名 end intellisense**/ /**details(命令行参数语法) 一、_ARGV 或 string.cmdline.argv 解析命名参数的语法规则 ------------------------------------------------------- 以斜杠或短横线开始的前导参数作为键。 自动移除一个或多个相同的前导字符作为键名。 如果前导参数包含等号,则以等号拆分为键值对,等号前后不应有空格, 否则检查下一参数如果没有相同的首字符则设为此键对应的值。 如果一个前导参数没有指定值,则默认值为空字符串(逻辑值为true)。 1. 参数名区分大小写 2. 以斜杠或短横线开始的前导参数作为参数名(参数名移除一个或多个相同的前导字符,区分大小写), 如果前导参数包含等号,则以等号拆分为参数名值对,等号前后不应有空格, 否则检查下一参数如果没有相同的首字符则设为此参数名对应的值, 如果一个前导参数没有指定值,则默认参数名为空字符串(逻辑值为 true)。 3. 包含空白字符、单引号、双引号、括号、花括号、方括号的参数仅识别为参数值,不作为参数名处理。 也就是说以下写法对于 string.cmdline.argv 或 _ARGV 是等价的 --name=value --name value -name value /name value 注意多次指定同名参数,则仅保存最后一次设定的值。 所有命名参数、非命名参数都会添加到解析返回参数表的数组成员中。 二、string.cmdline.argv2 解析命名参数的语法规则 ------------------------------------------------------- 除支持 string.cmdline.argv(str) 相同的功能与解析规则以外, string.cmdline.argv2(str,option) 增加以下规则: 单个 - 开头的命名参数解析为短参数。 短参数可以用空格分隔参数值,也可以省略分隔符(等号不作为分隔符)。 可在第 2 个调用参数中指定一个 @option 选项表。 @option 的所有键名用于指定待解析的命令行参数名字。 @option 预定义的单字符或多字符名字可作为短参数名、长参数名使用。 @option 预定义的单字母参数名允许作为短参数名合并到一个参数段。 @option 中参数名对应的值可以为任何非 false 值。 如果 @option 表中定义的值是函数,则每次解析对应名称参数时都会回调该函数。 回调参数 @1 为解析得到的参数值,而回调参数 @2 为将要返回的解析结果(参数表) 二、调用外部程序传命名参数的语法规则 ------------------------------------------------------- 命令行程序通常会用 / - 或 -- 作为参数名前导字符。 参数的名字与值以用空格分开。 很多程序同一个参数会提供长参数、短参数两个版本。 长参数名以 -- 开始,短参数名以 - 开始。 长参数或短参数一般都支持以空格分隔名字与值。 但长参数还可以用等号分隔其值,短参数还可以省略分隔符 例如 以 aria2 为例,以下几种写法是等价的: aria2 -j12 其他参数 aria2 -j 12 其他参数 aria2 --max-concurrent-downloads=12 其他参数 aria2 --max-concurrent-downloads 12 其他参数 有些时候可能不支持等号分隔值,空格分隔的兼容性可能更好一些 多个短参数可以合并。 例如"-v -i" 可以写为 "-vi" 。 有时候短参数后面可以跟另外一个键值对,例如 7zip 的参数: -mmt=on end details**/