🐙

シェルスクリプトで無理矢理テキストの形式を変更した話

2022/10/18に公開

はじめに

小説投稿のプラットフォームはLaTeX記法に対応していないので、LaTeX記法を自動でtxtに変換するシェルスクリプトを汲みました。

小説をLaTeX記法で書いている

私は趣味でLaTeX 記法で小説を書いています。
一般的なプログラミング言語とは違うものの、LaTeX記法をはじめとしたマークアップ言語は小説を含めて文章に意味づけをするうえで大変有効であり、また、そのままpdfに出力できるからです。
現に今、書いた小説をそのままpdfへ出力、校正を経て最終稿へ向けて書き進める、という順序をたどることができており、小説を書く上でLaTeX記法は私にとって手放せないものになりました。

小説投稿のプラットフォームはLaTeX記法を受け付けない

しかし、多くの小説投稿プラットフォームにそのまま投稿することはできません。
多くの場合、投稿フォームが受け付けているのはプレーンテキスト形式に独自のルビ記法などを追加した記法であるためです。
書いた文章がほぼそのままの見た目で読者に提供されるために、LaTeX記法で書かれたルビやシーン分け記号、コメントアウトなどがそのまま表示されてしまいます。
また、そもそも行頭空白もパラグラフの分け方も空行の作り方も特殊なため、それをそのままプレーンテキストとして扱うことはできません。また、それらを一般の記法に落とし込む方法もないため、手動で直すしかありませんでした。

手直しして投稿するのが嫌になったので自動化したい。

何十行、何百行という文章を手直しするのには限界があります。

  1. パラグラフを一行にまとめるために改行を削除
  2. ただし空行がある場合はその前後でパラグラフが分かれている
  3. パラグラフの先頭には全角空白
  4. 全角空白のうち!や?の後ろはそのままにしておく
  5. \\が書かれている場合は表示基準で空行が必要

軽く列挙しただけでも以上のルールが存在し、それに加えてさまざまなルールと調整が必要です。
今回はこれを自動化するべくシェルスクリプトを用いました。

シェルスクリプトを用いた理由

一番簡単に実装することができるため、シェルスクリプトを選択しました。
そのほかの手段としては、

  1. Rustでコマンドラインツールを実装
  2. Goでコマンドラインツールを実装
  3. ANTLRを利用
    などが挙げられますが、いずれも実装に対して工数が多くかかることが予想されました。
    反対に、シェルスクリプトであれば、もともとあるツールを組み合わせて利用することで完成するので、さほど手間はかかるまいと考え、シェルスクリプトを選択しました。

実装

実装の手順について説明します。
今回私はzshで実行するシェルスクリプトを作成しました。

sedコマンドとパイプ

Linux系OSでは、コマンドを|(パイプ)でつなぐことで、出力結果を引き継いで使うことができます。
sedコマンドは、正規表現を用いてファイル・文字列を編集することができるStream texteditorです。
この二つを組み合わせて、LaTeX記法からカクヨム記法へ変換するシェルスクリプトを組んでいきます。

スクリプト全体観

# LaTeX コマンド \ltjrubyをカクヨム記法に変更
sed -e 's/\\ltjruby{\(.*\)}{\(.*\)}/|\1《\2》/g' $INPUT_FILENAME |
# LaTeX コマンド \section からセクションタイトルを抽出
sed -e 's/\\section{\(.*\)}/\1/g' |
# LaTeX コマンド \scene を変更
sed -z 's/\\scene/\n◇◆◇\n/g' |
# LaTeX コマンド \clearpageを削除
sed -e 's/\\clearpage//g' |
# LaTeX コマンド % comment を削除
sed -e 's/%.*$//g' | 
# 空行を全角空白へ置換
sed -e 's/^$/ /g' |
# すべての改行を削除
sed -z 's/\n//g' |
# 全角空白が2つ以上存在した場合に1にする
sed -z 's/ \{2,\}/ /g' |
# 全角空白の前で改行
sed -z 's/ /\n /g' |
# 末尾が!であれば改行を削除
sed -z 's/!\n/!/g' |
# 末尾が?であれば改行を削除
sed -z 's/?\n/?/g' |
# 末尾が\\であれば削除して改行を追加
sed -z 's/\\\\\n/\n\n/g' |
# 行頭が全角空白と開き括弧である場合に全角空白を削除
sed -z 's/\n 「/\n「/g' |
sed -z 's/\n 『/\n『/g' |
sed -z 's/\n (/\n(/g' |
sed -z 's/\n 〝/\n〝/g' |
# 後処理
# 空行に余計な全角空白があれば削除
sed -e 's/^ $//g' |
# シーン分けマークの前にある全角空白を削除
sed -e 's/ ◇◆◇/◇◆◇/g' |
sed -e 's/◇◆◇/\n◇◆◇\n/g' > $OUTPUT_FILENAME

はい、かなり強引な実装です。
パイプで複数のsedを連結させて、最終的に指定されたファイル名に対して結果を吐き出させています。

まとめ

これを走らせることで、LaTeX記法で書いたファイルを通常のテキストファイルの形式で出力することができるようになりました。
このシェルスクリプトの実装はあまりよろしくなく、私の環境で動けばいいと考えて作ってあるものですので、参考にはならないかもしれませんがどうぞお試しください。

Discussion