我之所以遇到这个问题,是因为我对 OP 有类似的要求(解析可能包含带有嵌入空格的双引号参数的字符串)。但是,接受的答案并没有满足我的需要(它去除了空格,并且对参数的数量做出了过多的假设)。因此,我必须设计自己的解决方案,并在此提供,以防其他人发现它有用。
实际上有两种变体:第一种不允许允许双引号出现在生成的参数列表中;第二个确实通过在双引号字符串中使用双双引号(...""...)来允许这样做。 (我实际上是先写了这个版本,“因为 Windows 下的 Node 就是这样做的”,然后将其删减为第一个变体。
在这两个示例中,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 ) ;
// Find a unique marker for the space character.
// Start with '<SP>' and repeatedly append '@' if necessary to make it unique.
var spaceMarker = '<SP>' ;
while( commandLine.indexOf( spaceMarker ) > -1 ) spaceMarker += '@' ;
// Protect double-quoted strings.
// o Find strings of non-double-quotes, wrapped in double-quotes.
// o The final double-quote is optional to allow for an unterminated string.
// o Replace each double-quoted-string with what's inside the qouble-quotes,
// after each space character has been replaced with the space-marker above.
// o The outer double-quotes will not be present.
var noSpacesInQuotes = commandLine.replace( /"([^"]*)"?/g, ( fullMatch, capture ) => {
return capture.replace( / /g, spaceMarker ) ;
}) ;
log( 'noSpacesInQuotes', noSpacesInQuotes ) ;
// Now that it is safe to do so, split the command-line at one-or-more spaces.
var mangledParamArray = noSpacesInQuotes.split( / +/ ) ;
log( 'mangledParamArray', mangledParamArray ) ;
// Create a new array by restoring spaces from any space-markers.
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 下的 Node 如何解析命令行(未在 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 ) ;
// Find a unique marker for pairs of double-quote characters.
// Start with '<DDQ>' and repeatedly append '@' if necessary to make it unique.
var doubleDoubleQuote = '<DDQ>' ;
while( commandLine.indexOf( doubleDoubleQuote ) > -1 ) doubleDoubleQuote += '@' ;
// Replace all pairs of double-quotes with above marker.
var noDoubleDoubleQuotes = commandLine.replace( /""/g, doubleDoubleQuote ) ;
log( 'noDoubleDoubleQuotes', noDoubleDoubleQuotes ) ;
// As above, find a unique marker for spaces.
var spaceMarker = '<SP>' ;
while( commandLine.indexOf( spaceMarker ) > -1 ) spaceMarker += '@' ;
// Protect double-quoted strings.
// o Find strings of non-double-quotes, wrapped in double-quotes.
// o The final double-quote is optional to allow for an unterminated string.
// o Replace each double-quoted-string with what's inside the qouble-quotes,
// after each space character has been replaced with the space-marker above;
// and each double-double-quote marker has been replaced with a double-
// quote character.
// o The outer double-quotes will not be present.
var noSpacesInQuotes = noDoubleDoubleQuotes.replace( /"([^"]*)"?/g, ( fullMatch, capture ) => {
return capture.replace( / /g, spaceMarker )
.replace( RegExp( doubleDoubleQuote, 'g' ), '"' ) ;
}) ;
log( 'noSpacesInQuotes', noSpacesInQuotes ) ;
// Now that it is safe to do so, split the command-line at one-or-more spaces.
var mangledParamArray = noSpacesInQuotes.split( / +/ ) ;
log( 'mangledParamArray', mangledParamArray ) ;
// Create a new array by restoring spaces from any space-markers. Also, any
// remaining double-double-quote markers must have been from OUTSIDE a double-
// quoted string and so are removed.
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' ]