青春→鯖鰆みたいなやつ
今日、こんなツイートを見かけました。
娘1のクラスの寄せ書き、「楽しかったよ」「また会おうね」が多い中、キラリとひかる名文発見。「青春って魚編をつけると鯖鰆(サバサワラ)って読めるよね。似たような熟語を見つけたら教えて」By 町田高史(仮名)
— 藤川オレンジーナ (@Forangina) 2017年3月21日
彼が無事に社会に適応できますように。
ぼくもこういうのは大好きです。
(社会に適応できているかどうかは微妙なところです)
それで、こういうのを探してみることにしました。
漢字の構造については、漢字構造情報データベース(CHISE)というものがあります。
(かなりの労力がかかっていると思われるデータベースです。作られた方に感謝します。)
今回は、これを使わせていただきます。
% git clone http://git.chise.org/git/chise/ids.git
この中の IDS-UCS-Basic.txt が CJK 統合漢字のファイル、IDS-UCS-Ext-A.txt が CJK 統合漢字拡張 A のようです。
表示できない文字ばかり出ても面白くないので、今回はこの二つだけを使うことにします。
それと、元ツイートで言う「青春」のような、加工元の単語が必要です。
今回は、Wikipedia のタイトルを使うことにします。
% curl -LO https://dumps.wikimedia.org/jawiki/latest/jawiki-latest-all-titles.gz % gunzip jawiki-latest-all-titles.gz
後は、簡単な Perl のワンライナー(1行スクリプト)で、加工元の単語それぞれについて、「すべての文字に共通の部品を足すことができるもの」を探すだけです。
% perl -Mutf8 -CSD -F/\\t/ -nale 'if (@ARGV) { next if $F[2] =~ s{(\p{Han})}{$1}g < 2; for $i(0..length($F[2])-1) { $ch = substr($F[2], $i, 1); if ($ch =~ m{\p{Han}}) { $dict{$ch}->{substr($F[2], 0, $i).".".substr($F[2], $i+1)} = $F[1]; } } } else { next unless $F[1] =~ m{^(\p{Han}{2,})$}; %n=(); @n{split//, $F[1]}=(); next unless keys(%n)==length($F[1]); %t = (); while ($F[1] =~ m{(\p{Han})}g) { for $key(keys %{$dict{$1}}) { $t{$key}++; } } for $key(keys %t) { ($k=$key) =~ s{\P{Han}}{}g; $s=join("", map { $dict{$_}{$key}; } split(//, $F[1])); print "$F[1]+$k=$s" if $t{$key} == length($F[1]) and not exists $e{$F[1].$s}; $e{$F[1].$s} = (); } }' ids/IDS-UCS-Basic.txt ids/IDS-UCS-Ext-A.txt jawiki-latest-all-titles > list.txt
できたファイルはgistに置いてあります。
16万行もあるので見るのはちょっと大変です。
この中から、面白そうなものを見てみることにしましょう。
まずは、一番長いものです。
% perl -Mutf8 -CSD -nle '$dict{$_}=(); END { print for sort {length($b)<=>length($a)} keys %dict; }' list.txt | head
一番長いものは9文字でした。
世田谷区教育委員会+⺡=泄沺浴沤漖淯涹溳浍
連合国軍最高司令官+木=槤㭘椢楎樶槁柌柃棺
国土交通省大臣官房+木=椢杜校樋㮐杕栕棺椖
「世田谷区教育委員会」、全部さんずいがつけられるんですね。
次に、足す部品ごとに、一番長いものを探してみます。
% perl -Mutf8 -CSD -nle '@F=split/[\+=]/; $dict{$F[1]}=$_ if length($_) > length($dict{$F[1]}); END { print $dict{$_} for sort keys %dict; }' list.txt
いくつか拾うと、次のような感じです。
喜多見不動堂+⺖=憘恀悓怀慟憆
共産主義者同盟+⺘=拱摌拄㩘㨋挏擝
青少年委員会+⺼=腈䏚脌腇䐣脍
企業年金連合会+口=㖉㗼哖唫嗹哈哙
喜多見不動尊+火=熺㶴䙺炋㷲燇
風林火陰山雷+疒=瘋痳疢癊疝癗
連邦取引委員会+糹=縺綁緅紖緌縜絵
原子力安全委員会+艹=蒝芓艻荌荃萎蒷荟
世界長者番付+言=詍䛺䛫諸譒詂
月火水木金土+門=閒焛閖閑䦦䦌
軍人皇帝時代+魚=鯶魜鰉䱱鰣鮘
公民身分番号+鳥=䲲鴖鵢鳻鷭鴞
(Wikipedia に「日月火水木金土」という記事はないようですが、「間」があるので「間閒焛閖閑䦦䦌」と揃いますね)
ほかに、よく出てくる単語についても見てみます。
Wikipedia でリンクが張られている数が多いもの順にリストを作ります。
% curl -Ls https://dumps.wikimedia.org/jawiki/latest/jawiki-latest-pages-articles.xml.bz2 | bzcat | head -n 1000000 | perl -Mutf8 -CSD -nle '$dict{$1}++ while m{\[\[(\p{Han}{2,})\]\]}g; END { print for sort { $dict{$b}<=>$dict{$a} } keys %dict; }' > frequent.txt % perl -Mutf8 -CSD -nle 'if (@ARGV) { m{^(\p{Han}+)}; $dict{$1}->{$_}=(); } else { print for keys %{$dict{$_}}; }' list.txt frequent.txt > frequent_plus.txt
目視でいくつか拾ってみました。
大久保利通+木=杕杦椺梸樋
足利尊氏+⺡=浞浰澊汦
日清食品+艹=䒤蔳䓹䓵
武田信玄+女=娬㚼㜃妶
吉本新喜劇+口=咭呠噺嘻㘌
小林多喜二+亻=仦㑣侈僖仁
長宗我部元親+艹=萇萗莪蔀芫藽
最後に、この記事を公開するにあたって、はてなダイアリーは EUC-JP なので、EUC-JP で表せない漢字を実体参照にしました。
% perl -Mutf8 -MEncode -CSD -i.bak -ple 's{(\p{Han})}{ Encode::encode("shiftjis", $1) eq "?" ? sprintf("&#%d;", ord($1)) : $1; }ge;' draft.txt
やっぱり、こういうちょっとしたテキスト処理には Perl のワンライナーが便利です。
awk や sed やるぐらいなら Perl おすすめですよ!
ツイッターでぼくの言いたいことを言ってくれている人がいたので、ツイートを貼っておきます。
perl、素晴らしいものだと最近ようやく分かってきた。今まで誤解してた。いやまぁ単体の言語としては(?)微妙だけど、コマンドラインオプション諸々を含めた perl コマンドとしてみると拡張 grep、sed、awk といった感じで実に素晴らしい。
— にゃおきゃっと (@nyaocat) February 24, 2017
ミニマルperl読み進めてくたびに perl 最強かよという気持ちになるし、チマチマ find の難儀なオプションおぼえたり sed や grep や awk で使える正規表現の差を把握してしまったり BSD 環境で色々悲しくなってた過去の苦労、無駄だったな……という気分だ
— にゃおきゃっと (@nyaocat) February 24, 2017
単純なので xargs 覚えた時は xargs 最強やん!と思って find の -exec オプションや for とか書かなくなったし、awk 覚えたら大体 awk でいけるやん!となって cut とか使わなくなったし、perl 覚えた今は全部 perl でいいやん!となった
— にゃおきゃっと (@nyaocat) 2017年3月2日
マジで perl ワンライナー最強だなと日々感動するし多くのプログラマが学んだ方が良い、perl という言語ではなく perl というコマンドを学んだ方が良い
— にゃおきゃっと (@nyaocat) 2017年3月10日
紹介されているミニマル Perl、ぼくは読んだことがないので読んでみたいのですが、中古しかないのが残念です。
ところで、漢字に部首をつけるのが何の役に立つかを考えたのですが、検閲のある SNS などでヤバい単語を書くのにいいかもしれません。
リストを見ると、
本番行為+⺡=泍潘洐溈
本番行為+⺮=笨䉒筕䈧
本番行為+艹=苯蕃荇蒍
なんてのがありました。(ろくでもない)
*1:なぜ "shiftjis" にしているかは面倒なので略。