作 ▸
JavaScript 文字列をスペースでsplit、ただしダブルクォートの内側は残す
正規表現わかんないから普通にやった 。 ゚(゚^ω^゚)゚。
/**
* 文字列を半角スペースで区切る。ダブルクォートの内側は区切らない (エスケープされていれば区切る)。
* @param {String} str 文字列
* @return {Array} 区切られた文字列の配列
*/
function splitNicely(str) {
if (str !== String(str)) {
return [str];
}
const arr = [];
let buff = '';
let escaped = false;
let quoted = false;
for (let i = 0, len = str.length; i < len; ++i) {
const c = str.charAt(i);
if (c === '\\') {
escaped = true;
} else {
if (!escaped && c === '"') {
const prev = str.charAt(i - 1);
const next = str.charAt(i + 1);
if (!quoted && (prev === '' || prev === ' ')) {
quoted = true;
} else if (quoted && (next === '' || next === ' ')) {
quoted = false;
} else {
buff += c;
}
} else if (!quoted && c === ' ') {
arr.push(buff);
buff = '';
} else {
buff += c;
}
escaped = false;
}
}
arr.push(buff);
return arr;
}
// こんな感じ
console.log( splitNicely(`aaa "bbb" ccc`) ); // -> ["aaa", "bbb", "ccc"]
console.log( splitNicely(`a"aa b"bb c"c"c`) ); // -> ["a"aa", "b"bb", "c"c"c"]
通ったテスト
function assert(actArr, expArr) {
console.log('act=', actArr, 'exp=', expArr);
const len = actArr.length;
if (len !== expArr.length) {
throw new Error(actArr.length +' !== '+ expArr.length); // 要素数違ったらNG
}
for (let i = 0; i < len; ++i) {
if (actArr[i] !== expArr[i]) {
throw new Error(actArr[i] +' !== '+ expArr[i]); // 中身違ったらNG
}
}
}
assert( splitNicely(), [undefined] );
assert( splitNicely(null), [null] );
assert( splitNicely(``), [''] );
assert( splitNicely(`aaa`), ['aaa']);
assert( splitNicely(`aaa bbb ccc`), ['aaa', 'bbb', 'ccc'] );
assert( splitNicely(`aaa "bbb" ccc`), ['aaa', 'bbb', 'ccc'] );
assert( splitNicely(`a"aa b"bb c"c"c`), ['a"aa', 'b"bb', 'c"c"c'] );
assert( splitNicely(`"" aaa bbb ccc`), ['', 'aaa', 'bbb', 'ccc'] );
assert( splitNicely(`"aaa bbb" ccc`), ['aaa bbb', 'ccc'] );
assert( splitNicely(`aaa "bbb ccc"`), ['aaa', 'bbb ccc'] );
assert( splitNicely(`aaa "bbb ccc" ddd`), ['aaa', 'bbb ccc', 'ddd'] );
assert( splitNicely(`"\\"aaa bbb" ccc`), ['"aaa bbb', 'ccc'] );
assert( splitNicely(`"aaa bbb\\"" ccc`), ['aaa bbb"', 'ccc'] );
assert( splitNicely(`"aa\\"a b\\"bb" ccc`), ['aa"a b"bb', 'ccc'] );
assert( splitNicely(`"" "aa\\"a b\\"bb" ccc`), ['', 'aa"a b"bb', 'ccc'] );
assert( splitNicely(`GET 200 "http://aaa/bbb.html" "123 \\"456\\" 789" xxxxxx`), ['GET', '200', 'http://aaa/bbb.html', '123 "456" 789', 'xxxxxx'] );