未検証版
正規表現でも実装できますが、先読みのコストが高いのでお勧めはしません。
以下、未検証ですが、考え方の参考になれば。 (下記は期待通りに動きません)
JavaScript
1@(.*)(?:\n|$)(?=(?:@(?!\1\n).*\n)*(?!@\1(?:\n|$)))
動作確認版1 (前方一致で重複判定、一番最後の重複行を残す)
下記コードで期待通りに動作する事を確認しました。
mattnさんが掲示された事例にもマッチするよう、汎用的に行の重複削除するように(行頭が@で始まらなくても良い)書き直しました。
JavaScript
1'use strict';
2var string = '@aaa\n@bbb\n@ccc\n@aaa\n@ddd\n@eee\n@aaa',
3 search = /(?:\n|^)(.*)(?=(?:\n(?!\1).*)*\n\1)/g,
4 replace = '';
5
6console.log(string.replace(search, replace));
これは…順番に照合していって重複かどうか判断していくような構文でしょうか。
一行ずつ照合していくという意味ではそうですね。
テキストエディタの場合は「検索」と「置換」で文字列処理をしますので、重複削除するには空文字(''
)に置換する事になります。
「動作確認版1」に存在する問題点
今回は簡易的なサンプルであるが故に、比較的シンプルな正規表現となる事を目指しました。
あくまでもサンプルであり、叩き台にしてもらうべく書いた正規表現です。
仮に、「私が考える実用的な正規表現を書くこと」を試みるならば、「動作確認版1」にはいくつかの問題があるので、私はこの問題の修正を試みます。
- (問題1) 文頭(
^
) にマッチした場合に末尾の \n
が残る(一番初めに空行が一つ残る)
- (問題2) 前方一致で重複検索する (固定長文字列でなかった場合に誤爆する)
- (問題3) 前方から重複行を削除していき、最後に重複していない行を残す
(問題1) は「^
で始まる行」と「\n
で始まる行」を同一処理とし、\n
の削除が「\n
で始まる行」でしか行われない事に起因します。
解決するには、「^
で始まる行」と「\n
で始まる行」を双方とも行末の \n
を削除し、行頭の \n
を削除しない方向に修正すれば良いでしょう。
(問題2) は例題がほぼ「固定長文字列」であった為、重複判定処理をさぼりました。
具体的には、@aa\n@aaa
の文字列に対して、\n@aaa
を出力するという問題です。
@aaa
は @aa
で始まる為に重複判定が働いてしまいます。
行末判定が疎かなので、しっかりと行末を先読みすればこの問題は回避できます。
(問題3) は私は問題とは認識していませんでした。
要件では「重複行を削除する」としかなく、**「重複があった場合に、どの行を残すかまでは指定されていなかった」**からです。
仮に一番初めにマッチした行を残す仕様とするならば、先読みの代わりに後読みを使う事で解決できるでしょう。
動作確認版2 (完全一致で重複判定、一番最後の重複行を残す)
次の修正を施したとします。
- (問題1), (問題2) を解消する
- (問題3) はそのまま残す
コードをGitHubにUPしました。
v0.1.1 は後読みを使用している為、Google Chrome 62 以上でなければ動作しません。
v0.2.1 は後読みを使用せず、修飾子m(multiline)を使用しており、一般的なブラウザ全般で動作します。
テキストエディタで動作させる場合は、multilineオプションに対応しているかどうかで使い分けるといいでしょう。
一番初めにマッチした重複行を残すには
(問題3) ですが、「一番初めにマッチした行を残す仕様」にする場合は先読みを後読みに変更する事で改善する案が想像できますが、これはかなり難易度が高いようです(私が「後読みに関して熟知していない」という理由もあります)。
途中までは作成したので、興味がある方は挑んでみると面白いかもしれません。
JavaScript
1'use strict';
2function deleteDuplicateLine (string) {
3 return string.replace(/(?<=(?:^|\r\n|[\n\r])(.+)(?:(?:\r\n|[\n\r])(?!\1[\n\r])(.*))*)(?:\r\n|[\n\r])\1(?=[\n\r]|$)/g, '');
4}
更新履歴
- 2018/01/27 00:21 動作確認版1を追記
- 2018/01/28 14:19 「動作確認版1」に存在する問題点、動作確認版2、一番初めにマッチした重複行を残すには、を追記
- 2018/01/28 17:14 行末処理が不完全だった為、GitHubリンクを delete-duplicate-line-0.1.1.js, delete-duplicate-line-0.2.1.js に更新した
Re: LUCIA さん
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/01/26 08:56
2018/01/26 08:58
2018/01/26 15:24
2018/01/26 15:38
2018/01/26 15:41
2018/01/27 13:56
2018/01/27 15:22
2018/01/28 05:26
2018/01/28 06:25
2018/01/28 07:53
2018/01/28 08:15