String.prototype.indexOf
問題なく動きましたので、現象を再現可能なコードを開示する事をお勧めします。
JavaScript
1'use strict';
2console.log('「よ」'.indexOf('「よ')); // 0
残存する問題点
下記コードは質問文のコードをそのまま使用したものです。
質問の本題部分は ikedas さんの回答で解決できていますが、まだ問題が残っているように思います。
ローカル変数 lines
JavaScript
1var lines = []; // 抜き出した文字列
区切り文字が改行であるとは限らない為、変数名 lines
に違和感があります。
質問文のケースにあてはめても改行を含まない文字列に対して処理を行う事が可能です。
JavaScript
1console.log(createLinesCount('「あ」「漢」「alpha」', '「', '」')); // ["「あ」","「漢」","「alpha」"]
第三引数(検索終了文字)の省略
JavaScript
1// 検索終了文字が指定されていなければ、改行コードを終了文字にする
2if ( to_text == "" ) to_text = "\n";
to_text
が指定されなかった場合、undefined
として評価されますが、undefined == ""
は「偽」なのでこの条件式は正しく機能しません。
従って、第三引数を省略した場合に to_text.length
の部分で「TypeError 例外」が発生してしまいます。
JavaScript
1createLinesCount('「あ」\n「漢」\n「よ」\n「alpha」', '「'); // TypeError: Cannot read property 'length' of undefined
検索終了文字列が持つからないと無限ループする
JavaScript
1// 検索終了位置を取得
2end = start + from_text.length;
3end = text.indexOf(to_text, end) + to_text.length;
検索終了文字列('to_text')が見つからなかった時の配慮がありません。
仮に次のコードを実行した場合、
JavaScript
1createLinesCount('「あ\n「漢\n「よ\n「alpha', '「', '」')); // "」" が見つからないので無限ループしてしまう
検索終了文字列('"」"')が見つからない為に text.indexOf(to_text, end)
の評価値が -1 となり、to_text.length は 1 なので end が 0
にリセットされます。
すると、初めから検索をやり直すことになるので while 文が無限ループしてしまいます。
while(1)
while (1)
は無限ループになるリスクがある為、可能な限りループ継続条件となる条件式を与えてやるのが好ましいと思います。
前述の無限ループもwhile条件を見直すことで回避する事が可能です。
修正コード (String#indexOf版)
上記問題を修正したコードがこちら。
JavaScript
1'use strict';
2function extractFromString(targetString, startString, endString){ // 検索対象文字列, 検索開始文字列, 検索終了文字列
3 // 全ての引数を String 型に変換する
4 targetString = String(targetString);
5 startString = String(startString);
6 endString = arguments.length > 2 ? String(endString) : '\n'; // 検索終了文字が指定されていなければ、改行コードを終了文字にする
7
8 var startStringLength = startString.length, // 検索開始文字列の文字数
9 endStringLength = endString.length, // 検索終了文字列の文字数
10 extractedStrings = [], // 抜き出した文字列リスト
11 startPosition,
12 endPosition;
13
14 do {
15 startPosition = targetString.indexOf(startString, startPosition);
16
17 if (startPosition !== -1) {
18 endPosition = targetString.indexOf(endString, startPosition + startStringLength);
19
20 if (endPosition !== -1) {
21 extractedStrings.push(targetString.slice(startPosition, endPosition + 1));
22 startPosition = endPosition + endStringLength;
23 }
24 }
25 } while (startPosition !== -1 && endPosition !== -1);
26
27 return extractedStrings;
28}
29
30console.log(extractFromString('「あ」\n「漢」\n「よ」\n「alpha」', '「', '」')); // ["「あ」", "「漢」", "「よ」", "「alpha」"]
31console.log(extractFromString('「あ」「漢」「よ」「alpha」', '「', '」')); // ["「あ」", "「漢」", "「よ」", "「alpha」"]
32console.log(extractFromString('「あ」\n「漢」\n「よ」\n「alpha」', '「')); // ["「あ」\n", "「漢」\n", "「よ」\n"]
修正コード (正規表現版)
正規表現を利用するとスマートに実装できます。
JavaScript
1function extractFromString2 (targetString, startString, endString) {
2 // 正規表現化する為に文字列をエスケープする
3 startString = String(startString).replace(/(?=[$()*+\-.?\[]^{|}])/g, '\\');
4 endString = arguments.length > 2 ? String(endString).replace(/(?=[$()*+\-.?\[]^{|}])/g, '\\') : '\n';
5
6 return String(targetString).match(new RegExp(startString + '[^' + endString + ']*' + endString, 'g'));
7}
8
9console.log(extractFromString2('「あ」\n「漢」\n「よ」\n「alpha」', '「', '」')); // ["「あ」", "「漢」", "「よ」", "「alpha」"]
10console.log(extractFromString2('「あ」「漢」「よ」「alpha」', '「', '」')); // ["「あ」", "「漢」", "「よ」", "「alpha」"]
11console.log(extractFromString2('「あ」\n「漢」\n「よ」\n「alpha」', '「')); // ["「あ」\n", "「漢」\n", "「よ」\n"]
Re: nnahito さん