改行混じりのcsvをperlで処理する
ASPのデータベースからエクスポートされたcsvの集計作業ということで眺めてたら、セル内で改行がある・セル内にコンマがある、という腐ったデータでムカついた(「csvにエクスポート」するんだからコンマや改行の扱いをちょっと考えてくれりゃいいものを)
あちこちの管理画面でエクスポートというとcsv形式になってることが多い。
それをエクセルに読み込んで…
・行や項目の多いシートになると横スクロールに縦スクロールで大騒ぎ。
・改行が混じってるとその行だけセルが異様に広がっていて目障り。
・csvの値は属性を持ってないのでエクセルが勝手に判断してただの数値を日付表示にしたり意味不明の表示になっていることなどざらにあってイライラさせられる。
こういうデータをエクセル上で手作業すると簡単に間違う。わたしは。
なもんで、perlで読み込んで一括処理・集計した方が早いし確実。その場限りの使い捨てのスクリプトを書いて対応している…ところが、perlやAWK、sedなどは行単位での処理が基本。改行の混じったcsv、まさに今回のようなcsvデータは扱いが面倒くさい。
ということで今日もまた 「Perlメモ」 のお世話になりました。
perlでセルに改行やコンマが入っているcsvデータを処理する。
(出典:https://www.din.or.jp/~ohzaki/perl.htm)
このまま利用させていただきました(ありがとうございます)
今さら知ったこと気づいたこと。
正規表現のパターンマッチは、リストコンテキストで評価すると()でくくった正規表現でひっかかった部分文字列のリストを返す。
今までこんなケースでは修飾子「g 」は使えないもんだとばかり思っていて 1 while(s/(.+)/$1/) など1つずつパターンマッチさせて処理していた。
scalar関数。リストの要素を数えるぐらいしか使ってなかったんだけど、今回このスクリプトでの使い方がまるでわからず調べてみたところ
https://perldoc.jp/func/scalar
scalar は単項演算子なので、EXPR として括弧でくくったリストを使った場合、 これはスカラカンマ表現として振舞い、最後以外の全ては無効コンテキストとして 扱われ、最後の要素をスカラコンテキストとして扱った結果が返されます。
ここでは「””」を「”」にするために使っている。
mapの条件式で部分文字列が「”」で括られていたら、scalar関数に文字列を渡して
「部分文字列をscalar関数のデフォルトに入れて、「””」を「”」に置換して、デフォルトの$_を返す」
左から順番に評価していって、コンマで繋いで各々の結果を切り捨てて、最後に残った式の結果を返すためだけにscalar関数を使っている。トリッキーで面白いなあ。これはループの中で使い途がある。
勉強になりました。
「perlパズル」
↑以前書いた、コンマの使い方のメモ
» ローカル環境で電子書籍を作る、Macアプリ・Windows版ツール 「かんたんEPUB3作成easy_epub」
ストアごとのリンク生成
今日時点、ウチが電子書籍で有料販売しているのは kindleストアと iBookstoreの2つ(無料販売をしているのはiBookstoreとgoogle playブックス、楽天koboの3つ)
ひとつのタイトルを複数のストアで販売しているような場合、ほとんどのところがやってるように「タイトルがあってそこにストアが複数ぶら下がる」表示形式の方が当然わかりやすい…kindleで始まっちゃったもんだから、データの持ち方を間違えていてAmazonのasinをキーにしているので修正が面倒くさいということもあって放置してた。また、AWSのこともあってウチのサイトはあちこちにasinを使ってるはずなんだけど、5分前の自分はすでに他人なので、まるで覚えていない。
影響範囲が大きいので別ページで試してから徐々に修正していく(徐々にkindle以外にも並べるべく)
まずは 「EPUB3::かんたん電子書籍作成」 の右サイドのコンテナでお試し。データベースはいじらずにスクリプトに配列をベタベタ書いて作ってみた。
スクリプト自体は使い回しだし、目新しいこともなく簡単に出来たんだけど、ちょっと気になったのがレギュレーション。
ストアへリンクするのにロゴなど画像を使った方がキャッチーでわかりやすいのは間違いない。kindleの利用規約や商標利用に関するページや、App Storeマーケティグガイド系のPDFをざっとみて…よくわからなかったのでロゴ画像を使うのはやめた。
(といいつつ、App StoreのPDFはこんな使い方しちゃダメですよ、と画像つきでレギュレーション解説があってわかりやすかったです、はい)
サイトを辿ってみると、デザインに合わせてロゴを加工して使ってるところがあるなあ。
また(c)表示も GyaO https://gyao.yahoo.co.jp/ct/anime/ を見るとページの一番下にごちゃーっとひとくくり。昔から雑誌なんかでも見るやり方ではあるけど、本当なら作品の近くになきゃいけない、はず。
目立たないのでOKのケース、力関係でOKのケース。
ということで、小心者で善良な納税者のわたしは触らぬなんちゃらの日和見。うーん、我ながらデザインだせえ。
今回のperl小ネタ。配列を order by random。
(出典:https://www.din.or.jp/~ohzaki/perl.htm)
いつも参考にさせていただいている 「Perlメモ」 のまんま(ありがとうございます)
今さらながら配列のスライスでこんなことができる(for文の最後の行)なんて知らなかった。
[06/19 08:37:59] 追記。
この雑記帖の上に配置してみた。
・カテゴリ電子書籍一覧を表示している時
・ひとつの記事を表示している時
の2パターン。うるさかったら外そうと思ったけど意外に違和感もなかったのでアクセスの様子見してみる。
» ローカル環境で電子書籍を作る、Macアプリ・Windows版ツール 「かんたんEPUB3作成easy_epub」
一発芸:Kindleサンプル表示セット
KDP用にサンプルチェックをするだけ、というスクリプトを書いたついでに、もう少しそれっぽくサンプルを表示できるようなセットを作ってみたので公開してみます。
https://t2aki.doncha.net/tmp/kindle-sample.html
サンプルと書かれたリンクをクリックするとkindleから公開されているサンプルを取得して、縦書きで表示します(残念ながらFirefoxなどは横書き)例によって一発芸ネタなので投げっぱなしで失礼。
kindleのサンプルを取得するためのCGIファイルと、表示のためのJavascriptとスタイルシート(縦書き)、それとサンプルのHTMLファイルの構成。
やることは以下の3つ。
・cgiファイルを自分のサーバーの実行可能なディレクトリにアップロード
・javascriptとcssを所定のディレクトリにアップロード
・HTMLの各該当部分を編集。
てな感じ。ちょっと面倒くさいです。
表紙画像は自分の作品なら自分で用意しましょう。
実際にAmazonのkindleストアでサンプルをダウンロードして確認してるひとがどのぐらいいるのか不明だけど、少なくともわたしはいきなり買っちゃう。ので、自分のサイトがあるならそこでサンプル表示をして見てもらえるならそれはそれでいいよなあ、ということで思いつき。
中身的には、単純に公開されているサンプルを取ってくるだけで、AWSのOAuth認証なんかも不要だしアフィリエイトタグもいらないので簡単。
公開されているサンプルが使っているタグは(表示に関係してるのは)h1とPタグ程度。
取得した時に全体を「kindle-sample」というクラスをつけたdivで囲んでるので、kindle-sample.cssを適当に書き換えてもらえれば横書きなどもできます。
ソースが汚いのは素人芸だから勘弁してください。
[04/23 17:52:52] 追記。
ちなみに、縦書きなどスタイルのカスタマイズが不要であれば、
ttp://kindleweb.s3.amazonaws.com/content/ASIN/gz_sample.html
このURLのASINの部分を、表示させたいkindleのASINコードにしてインラインフレームでやればそれだけでOKです。
» ローカル環境で電子書籍を作る、Macアプリ・Windows版ツール 「かんたんEPUB3作成easy_epub」
めも:perlでcsvデータ
最近あまりスクリプトを書いてなくて、いざ書こうと思ったら忘れていてビックリしたのでメモ。
csv(コンマ区切り)に限らずタブ区切りでも同じく。
DBIを使ってデータベースと同じように扱うモジュールもあるけど、そこまでのスペックは不要で、とりあえず目の前にあるエクセルや管理ページからダウンロードしたcsvを扱えればそれだけでOKというところ。
コンマやタブで区切られて、ヘッダがついていてデータが並んでいる
てな感じのデータ。
これを split してそのまま配列に入れればいいだけなんだけど、
単純に区切りでバラして配列に入れただけだと、データを取り出す時に $w[1] などと書くことになる。それよりはハッシュ(連想配列)にして $_->{title} などとヘッダでつけた名前(キー)で取り出せた方が間違いも少ない。
ヘッダをキーにしてデータを入れて取り出せるようにするのが以下(改行やEncodeなどは省略)
たぶんここがハッシュ(連想配列)の面白い書き方。
ヘッダ(文字)の配列をキーに、データの配列を値に一度に入れてしまう部分。
これのおかげで、カラム数が100とか200とか多くてもへっちゃら。
@bufという配列に一行ずつハッシュとして入って、データの取り出しもキー(名前)でわかりやすく。
てのを、仕事でもプライベートでも何度もあちこちで使い捨てで書き散らしていたんだけど、メモがどこにも残ってなかったので改めて。
どうでもいいけど、「ハッシュ」って色気がないよなあ。せっかく「連想配列」というそそられる名前があるんだからこちらを使うべき。
» ローカル環境で電子書籍を作る、Macアプリ・Windows版ツール 「かんたんEPUB3作成easy_epub」
epub2のtoc.ncxをepub3の目次に変換
Sigilなどで作られるepub2ファイルをepub3ファイルに変換するための小ネタ。
・各xhtmlファイルのヘッダを書き換える
これはエディタのマクロや、スクリプトで一括可能。複数のファイルに対して検索置換できるエディタがあればこういう時に重宝する。
・opfファイルを書き換える
metadata部
epub3の書式に合わせて書き直し…ってほぼそのままでイケるような気がするけど、既存のEPUB3ファイルのopfファイルを開いてコピペ、それをひな形にしてepub2の方から必要なものを移植するのが確実かな。
manifest部
toc.ncxがらみの記述を削除。
新たにナビゲーション文書を設定・指定する。各プロパティ指定を確認。
spine部
toc.ncxがらみを削除。あとはそのまま。
guide部
まるごと削除
エディタやスクリプトで一括が可能だと思うけど、metadata部がちょっとメンドクサイので手作業コピペ。
・ナビゲーション文書を新規作成する。
ナビゲーション文書(たとえばnav.xhtml)を新たに作る必要がある。いまのところ、目次とランドマーク。ランドマークはopfファイルにguide部があれば、それをコピペして編集すればイケる。
epub2のtoc.ncxをepub3目次用のリストに変換するのが以下のスクリプト。
まとめて全部、一括変換するスクリプトを書こうとうだうだやってたんだけど、metadataの差の吸収が意外に面倒くさいので投げた。今日のところは。
…気力があったらそのうちスクリプトを書いて、もう少し丁寧に説明を書いておくかなぁ。
» ローカル環境で電子書籍を作る、Macアプリ・Windows版ツール 「かんたんEPUB3作成easy_epub」
perlで扱うutf8フラグやutf-8-macの小ネタ
perlのスクリプトでmacの日本語ファイル名がマッチしない、という話題がtwitterに上がっていた。ネタ的に面白そうなので自分でも試してみたところ、macの日本語ファイル名が正規表現で一致しないことに気づいて、ちょっと吃驚。
フォルダには
・test.txt
・あいうえお
・ペダル
・memo.txt
など、アルファベットのファイルや日本語ファイル・フォルダが雑多に入っている。
この中から「あいうえお」と「ペダル」だけを検索で引っ張り出したい。というのが以下のスクリプト。
ところが、これでヒットするのは「あいうえお」だけで、「ペダル」はヒットしない。
twitterでの流れを追うとどうやらmacのファイルシステムが(日本語ファイル名に)使うのは NFD という形式らしい(Normalization Form Canonical Decomposition)。これをperlで判定するためには NFC という形式に変換してやる必要がある(Normalization Form Canonical Composition)
NFDとNFCで問題になるのが。
・濁音などがはいると文字コードが違ってくる。
・macの場合はさらに一般的なNFDではなくて、utf-8-mac というちょっと特殊なもの。
『Geekのメモ: Mac OS Xのファイルシステムの文字コード』
↑こちらのページが具体的でわかりやすかった(感謝!)
お馴染みの Data::Dumper で読み込んだファイル名と、スクリプト内の文字を比べると、文字コードが違っていた。まさに上記した utf-8-mac の問題。「あいうえお」は濁音が混じってないので文字コードは同じだけど、「ペダル」は濁音部分で文字コードが違っていた・文字長が増えていた。
上記サイトを参考に、CPANから Text::Iconv をダウンロード、インストールしてテストスクリプト。
1)ファイル名を utf-8-mac から、utf-8に変換する。
2)変換したファイル名にutf8フラグをつける。
↑で、無事確認できた。
ついでに。utf8フラグのおさらい。
文字コードのutf8とperl のutf8フラグは別モノ。
perlがスクリプトで内部処理するのにつけるのがutf8フラグということ…って、素人のわたしはよくわかってないので検証。
コマンドラインで引数に渡したファイルを読み込んで、「弱虫ペダル」を含んだ行を出力(プリント)するだけの単純なスクリプト。
・スクリプト自体は文字コード、utf8で書かれている。
・「弱虫ペダル」は文字コードがutf8で、 use utf8 によって、perl の utf8フラグがついている。
・最初の if 文は、utf8フラグのついていないテキストと、utf8フラグのついた「弱虫ペダル」の比較なのでヒットしない。
・Encode::decode で読み込んだファイルのテキストにutf8フラグをつける。
ENCODE-NAMEはファイルの文字コード。shiftjis、 utf8など。
・次の if 文は utf8フラグのついているテキストと、utf8フラグのついた「弱虫ペダル」の比較なので文字コードが * shiftjisだろうがutf8だろうが * ヒットする。
・スクリプトの文字コードはutf8でも、use utf8をつけない場合(スクリプトにutf8フラグがつかない場合)
・「弱虫ペダル」は文字コードがutf8で、perl の utf8フラグはついていない。
・最初の if 文では入力ファイルの文字コードが utf8 のものだけがヒットする。
・Encode::decode で読み込んだファイルのテキストに utf8 フラグをつける。
・次の if 文は utf8 フラグがついているテキストと、utf8フラグのついていない「弱虫ペダル」の比較なのでどれもヒットしない。
perl の utf8 フラグをつけることによって、スクリプトや、入力されるテキストの文字コードは何でも構わない、という超便利なフラグ(decodeで正しい文字コードを指定する必要はあるけど)
perlのutf8フラグネタでは以前 「utf8移行と自分メモその2」 こっちにも覚え書き(utf8フラグをつけたスクリプトは、変数に日本語が使える、というネタはこちら)
encodeネタでは変換に失敗する文字をチェックするのにencodeの第3引数に、というネタも 「メモ encodeで変換失敗を第三引数でフォロー」 …ほんと、なんちゅーかほんちゅーか。面倒くさい。
話の発端からtwitterを追ってみると、utf16だったことが原因だったということでした。
て、utf16使う状況があるのか!?参考になります。ううううむ。難物。
» ローカル環境で電子書籍を作る、Macアプリ・Windows版ツール 「かんたんEPUB3作成easy_epub」