2011/05/09

xyzzy で重複行を削除する



CSVファイルとか、XMLのタグ抽出したりとかで、何かと必要になることが多いのが重複行の削除。

xyzzy では C-x # uniq して、外部の uniq.exe を使うのがデフォの様子。

だけど、これぐらいの日常タスクなら xyzzy だけでやりたいと思ったから適当に書いといた。



  • 範囲はリージョンで指定する

  • 連続して重複していようが、ばらけていようが、2回以上の出現は重複とみなす

  • ならびは元のデータに合わせる

  • 大文字小文字区別 あり uniq-line-region

  • 大文字小文字区別 なし uniq-line-region-case-insensitive

下のようになる。

(元データ)   uniq-line-region    uniq-line-region-case-insensitive
----------   ----------------    ---------------------------------
AAA          AAA                 AAA
ccc          ccc                 ccc
CCC          CCC                 xxx
aaa          aaa                 BBB
AAA          xxx
aaa          BBB
xxx          bbb
BBB
bbb
ccc
aaa
bbb
aaa
aaa


(defun uniq-line-region (from to &optional case-insensitive)
"重複行を削除する。case-insensitive を省略するか nil の場合は、大文字小文字の区別をする。
non-nil のときは大文字小文字を区別しない。"
(interactive "*r")
(save-excursion (save-restriction
(narrow-to-region from to)
(goto-char (point-min))
(let (l)
(loop
(let ((s (buffer-substring (progn (goto-eol) (point)) (progn (goto-bol) (point)))))
(unless (member s l :test (if case-insensitive #'string-equal #'string=))
(setq l (cons s l)))
(unless (forward-line 1) (return))))
(delete-region from to)
(with-output-to-selected-buffer
(map nil #'(lambda (x) (format t "~A~%" x)) (nreverse l)))))))

(defun uniq-line-region-case-insensitive (from to)
"重複行を削除する。大文字小文字を区別しない。"
(interactive "*r")
(uniq-line-region from to t))


似たようなタスクとして、リージョンをソートしたいときは下記が参考になる。






Related Posts Plugin for WordPress, Blogger...

0 コメント :

コメントを投稿