我之所以要问这个问题,是因为我对OP有类似的要求(解析可能包含带嵌入空格的双引号参数的字符串)。然而,被接受的答案并没有满足我的需要(它去掉了空格,并对参数的数量做了太多假设)。因此,我必须设计自己的解决方案,我在这里提供,以防其他人发现它有用。
实际上有两种变体:第一种变体
不
允许双引号出现在生成的参数列表中;第二个
做
允许使用双引号(
...""...
)在双引号字符串中。(实际上是我先写的这个版本)
因为Windows下的节点就是这样做的
“然后在第一个变体中减少它。
在这两个例子中
log()
函数,并从内部调用它
splitCommandLine()
,仅用于显示内部工作,可以省略。
简单双引号字符串
-
参数通常会在空间上拆分。
-
双引号字符串被视为一个参数,即使它们包含空格。
-
多个空间
在内部
双引号将被保留。
-
多个空间
外部
双引号它们将被视为一个空格。
-
如果缺少最终的收盘双引号,则将假定为该双引号。
-
无法在参数中输入双引号字符。
splitCommandLine( 'param1 " param 2" param3 "param 4 " "param 5' ) ;
log( 'argv', process.argv.slice(2) ) ;
function log( n, v ) {
console.log( n ) ;
console.dir( v ) ;
console.log() ;
}
function splitCommandLine( commandLine ) {
log( 'commandLine', commandLine ) ;
var spaceMarker = '<SP>' ;
while( commandLine.indexOf( spaceMarker ) > -1 ) spaceMarker += '@' ;
var noSpacesInQuotes = commandLine.replace( /"([^"]*)"?/g, ( fullMatch, capture ) => {
return capture.replace( / /g, spaceMarker ) ;
}) ;
log( 'noSpacesInQuotes', noSpacesInQuotes ) ;
var mangledParamArray = noSpacesInQuotes.split( / +/ ) ;
log( 'mangledParamArray', mangledParamArray ) ;
var paramArray = mangledParamArray.map( ( mangledParam ) => {
return mangledParam.replace( RegExp( spaceMarker, 'g' ), ' ' ) ;
});
log( 'paramArray', paramArray ) ;
return paramArray ;
}
使用与代码中嵌入的命令行相同的命令行运行此命令,表明它生成的输出与Node/Windows命令行解析器相同:
C:\>node test1.js param1 " param 2" param3 "param 4 " "param 5
commandLine
'param1 " param 2" param3 "param 4 " "param 5'
noSpacesInQuotes
'param1 <SP><SP><SP>param<SP><SP><SP>2 param3 param<SP><SP>4<SP><SP> param<SP>5'
mangledParamArray
[ 'param1',
'<SP><SP><SP>param<SP><SP><SP>2',
'param3',
'param<SP><SP>4<SP><SP>',
'param<SP>5' ]
paramArray
[ 'param1', ' param 2', 'param3', 'param 4 ', 'param 5' ]
argv
[ 'param1', ' param 2', 'param3', 'param 4 ', 'param 5' ]
带双引号的双引号字符串
-
与第一个例子完全相同,
除了
在双引号字符串中,双引号(
..."aaa ""bbb"" ccc"...
)将在解析的参数中插入双引号(
aaa "bbb" ccc
)。在双引号字符串之外,双引号将被忽略。这模拟了Windows下的节点解析命令行的方式(未在Unix变体上测试)。
splitCommandLine( 'param1 " param 2" param""3 "param "" 4 " "param 5' ) ;
log( 'argv', process.argv.slice(2) ) ;
function log( n, v ) {
console.log( n ) ;
console.dir( v ) ;
console.log() ;
}
function splitCommandLine( commandLine ) {
log( 'commandLine', commandLine ) ;
var doubleDoubleQuote = '<DDQ>' ;
while( commandLine.indexOf( doubleDoubleQuote ) > -1 ) doubleDoubleQuote += '@' ;
var noDoubleDoubleQuotes = commandLine.replace( /""/g, doubleDoubleQuote ) ;
log( 'noDoubleDoubleQuotes', noDoubleDoubleQuotes ) ;
var spaceMarker = '<SP>' ;
while( commandLine.indexOf( spaceMarker ) > -1 ) spaceMarker += '@' ;
var noSpacesInQuotes = noDoubleDoubleQuotes.replace( /"([^"]*)"?/g, ( fullMatch, capture ) => {
return capture.replace( / /g, spaceMarker )
.replace( RegExp( doubleDoubleQuote, 'g' ), '"' ) ;
}) ;
log( 'noSpacesInQuotes', noSpacesInQuotes ) ;
var mangledParamArray = noSpacesInQuotes.split( / +/ ) ;
log( 'mangledParamArray', mangledParamArray ) ;
var paramArray = mangledParamArray.map( ( mangledParam ) => {
return mangledParam.replace( RegExp( spaceMarker, 'g' ), ' ' )
.replace( RegExp( doubleDoubleQuote, 'g' ), '' ) ;
});
log( 'paramArray', paramArray ) ;
return paramArray ;
}
同样,这段代码以与Node/Windows相同的方式解析命令字符串:
C:\>node test2.js param1 " param 2" param""3 "param "" 4 " "param 5
commandLine
'param1 " param 2" param""3 "param "" 4 " "param 5'
noDoubleDoubleQuotes
'param1 " param 2" param<DDQ>3 "param <DDQ> 4 " "param 5'
noSpacesInQuotes
'param1 <SP><SP><SP>param<SP><SP><SP>2 param<DDQ>3 param<SP>"<SP>4<SP><SP> param<SP>5'
mangledParamArray
[ 'param1',
'<SP><SP><SP>param<SP><SP><SP>2',
'param<DDQ>3',
'param<SP>"<SP>4<SP><SP>',
'param<SP>5' ]
paramArray
[ 'param1', ' param 2', 'param3', 'param " 4 ', 'param 5' ]
argv
[ 'param1', ' param 2', 'param3', 'param " 4 ', 'param 5' ]