Perl
Markdown

Markdownの見出しにアウトライン番号を付ける独自仕様を追加する。(独自仕様のMarkdownファイルを通常のMarkdownファイルに変換するperlスクリプトを作成する)

More than 3 years have passed since last update.


内容

Markdownの見出しにアウトライン番号を付けたいと思った。

手動で直接書けば良いのだが、メンテナンスを考えると自動化したい。

例えば、

#1. title1

#1. title2
##1. title2-1
##1. title2-2

と記載すると以下のように表示されるようにしたい。

▼ ----- サンプル開始 ----- ▼


1. title1


2. title2


2.1. title2-1


2.2. title2-2

▲ ----- サンプル終了 ----- ▲

そこで、上記記述で作成した「独自仕様Markdownファイル」を「通常のMarkdownファイル」に変換するperlスクリプトを作成することで実現することにした。

あまり時間をかけたくないため、また、個人でしか使用しないため、エラー処理や細かい仕様などは完全無視する。


スクリプト

仕様などはコメントに記載したので、そちらを参照してください。

#!/usr/bin/perl

# -------------------------------------------------------------------------
# Name : convmd.pl
# Purpose :
# アウトライン番号付き見出し(下記Note参照)を通常のMarkdownで使用できる
# 文字列に変換し、結果を標準出力に出力する。
# Usage : convmd.pl <独自仕様Markdownファイル>
# Output : 通常のMarkdown文字列
# Example : convmd test.md > output.md
# Note :
# アウトライン番号付き見出しについて
# アウトライン番号付き見出しとは、独自に拡張したMarkdown書式で、
# "#1. " ... "######1. "で始まる。
# 通常のMarkdownで使用するには、以下のように変換する必要がある。
# 変換仕様1:見出しレベル別に、以下のように変換する。
# "#1. str" → "# 1. str"
# "##1. str" → "## 1.1. str"
# "###1. str" → "### 1.1.1. str"
# "####1. str" → "#### 1.1.1.1. str"
# "#####1. str" → "##### 1.1.1.1.1. str"
# "######1. str" → "###### 1.1.1.1.1.1. str"
# 変換仕様2:以下の通り、連番を付ける。
# "#1. str1" → "# 1. str1"
# "#1. str2" → "# 2. str2"
# "#1. str3" → "# 3. str3"
# 変換仕様3:見出しレベルに合わせて連番を付ける。
# "#1. str1" → "# 1. str1"
# "##1. str1-1" → "## 1.1. str1-1"
# "##1. str1-2" → "## 1.2. str1-2"
# "###1. str1-2-1" → "### 1.2.1 str1-2-1"
# "###1. str1-2-2" → "### 1.2.2 str1-2-2"
# "##1. str1-3" → "## 1.3. str1-3"
# 変換仕様4:見出しレベル6まで対応する。
# Remarks :
# 作成時間を短縮するため、また、個人でしか使用しないため、エラー処理や
# 細かい仕様などは完全無視。
# 問題が発生したら、その都度対応。
# -------------------------------------------------------------------------

# 初期設定
@outlineNums=(0, 0, 0, 0, 0, 0, 0); # $levels[0]は使用しない。
$maxLevel=6; # "#1. "〜"######1. "まで対応。

# Markdownファイルの読み込み
open(IN,$ARGV[0]);
@fileData=<IN>;
close(IN);

# 変換処理
foreach my $line (@fileData) {
if ($line =~ /^(#+)1\. (.+)/) {
# アウトライン番号付き見出しの場合の処理

# レベル数(#の数)の取得
my $level=length($1);

if ($level<=$maxLevel){
# 該当するレベルのアウトライン番号を加算
$outlineNums[$level]++;

# 該当するレベル以下のアウトライン番号をリセット
for (my $i=($level+1); $i<=$maxLevel; $i++) {
$outlineNums[$i]=0;
}

# アウトライン番号文字列作成
$outlineNumsStr="";
for (my $i=1; $i<=$level; $i++) {
$outlineNumsStr.="$outlineNums[$i].";
}

# 通常のMarkdownで使用できる文字列を生成
$line=sprintf("%s %s %s\n", $1, $outlineNumsStr ,$2);
}
}

# 結果を出力
print "$line";
}

exit 0;


実行例

▼ 独自仕様Markdownファイル(sample.org.md)


sample.org.md

#1. aaa

#1. bbb:
##1. bbb-1
##1. bbb-2
#1. ccc:
##1. ccc-1
##1. ccc-2
###1. ccc-2-1
###1. ccc-2-2
#1. ddd

▼ 実行

convmd.pl sample.org.md > sample.md

▼ 実行後 (sample.md)


sample.md

# 1. aaa

# 2. bbb:
## 2.1. bbb-1
## 2.2. bbb-2
# 3. ccc:
## 3.1. ccc-1
## 3.2. ccc-2
### 3.2.1. ccc-2-1
### 3.2.2. ccc-2-2
# 4. ddd


メモ


perl

▼ マッチした文字列の取り出し

$str="##1. title text";

if ($str =~ /^(#+)1\. (.+)/) {
print "1-> $1\n"; # ##
print "2-> $2\n"; # title text
}

▼ 同じ文字列を繰り返して連結

# aを5個連結

print "a" x 5;
# aaaaa

▼ 引数の取り出し

print $ARGV[0];

print "\n";
print $ARGV[1];
print "\n";
print $ARGV[2];
print "\n";

if (@ARGV != 1){
print "ERROR!\n";
}

▼ ファイルの読み込み

if (@ARGV != 1){

print "ERROR!\n";
exit 1;
}

open(IN,$ARGV[0]);
@data = <IN>;
close(IN);

foreach (@data) {
print;
}