0

解析したい文字列があり、それは github マークダウンに少し似ていますが、完全な実装は本当に望んでいません。文字列は、「コード」ブロックと「テキスト」ブロックの混合になります。コード ブロックは、3 つのバッククォートの後にオプションの「言語」が続き、次にコードが続き、最後にさらに 3 つのバッククォートが続きます。非コードは、ほとんどすべてのものになります。ユーザーが「テキスト」ブロックに 3 つのバッククォートを入力できなくても、気にしません (気にする必要があるかもしれません)。ここに例があります...

これはコードブロックが続くテキストです
ルビー
デフ関数
   "こんにちは"
終わり
```
もう少しテキスト

もちろん、さらに多くのコードとテキスト ブロックが散在している可能性があります。私はこれのための正規表現を書いてみましたが、うまくいくように見えましたが、すべての一致を与えるグループ (括弧内) を取得できず、scan() は順序を失いました。いくつかの Ruby パーサー (treetop、parselet) の使用を検討しましたが、私が望むものには少し大きく見えますが、それが私の最良の選択肢である場合は、喜んでそのルートに進みます。

考え?

何人かの人々が私が試していたREを求めてきました(以下の多くのバリエーション)...

re = 
  /
    ```\s*\w+\s*          # 3 backticks followed by the language
      (?!```).*?          # The code everything that's not 3 backticks
    ```                   # 3 more backticks
    |                     # OR
    (?!```).*             # Some text that doesn't include 3 backticks
  /x                      # Ignore white space in RE

たとえば単純なケースでも

md = /(a|b)*/.match("abaaabaa")

a と b のすべてを取得することはできません。存在しないmd [3]と言うから。それがより理にかなっていることを願っています。そのため、私の場合は RE が機能するとは思いませんが、間違っていることが証明されてもかまいません。

4

1 に答える 1

1

Markdown (github-、stackoverflow-flavors) とあなたの質問 (残りのテキストに関してはあまり正確ではありません) に関する私の知識に基づいて、ここでいくつかの仮定を立てます。

1. すべてのコード ブロックは、3 つのバッククォート、オプションの言語名、および改行文字のみを含む単一の行で始まります。

2. すべてのコード ブロックは、3 つのバッククォートのみを含む単一の行で終了します。

3. コード ブロックは空ではありません。

これらの仮定を受け入れることができれば、次のコードが機能するはずです (テキストがstr変数にあると仮定します)。

regex = %r{
  ^```[[:blank:]]*(?<lang>\w+)?[[:blank:]]*\n # matches start of codeblock, and captures optional :lang.
    (?<content>.+?) # matches codeblock content and captures in :content
  \n[[:blank:]]*```[[:blank:]]*\n # matches ending of codeblock.
}xm # free-space mode and . matches newline.
position = 0
matches = []
while(match = regex.match(str,position)) do
  position = match.end 0
  matches << [match[:lang], match[:content]]
end

After this matches には配列の配列が含まれます。この配列の内部配列は、最初の要素が (オプションの) 言語 (nil の場合もある) であり、2 番目の要素がコンテンツである一致を表します。

テキストにさらに仮定がある場合は、正規表現を変更できます。

これは私が使用したテスト文字列です:

str = %{
this is some random text.
```ruby
  def print
    puts "this is a code block with lang-argument"
  end
```

some other text follows here.
i want some ``` backticks here.

```
  def print
    puts "this is a code block without lang-argument"
  end
```
}
于 2012-08-18T18:51:50.847 に答える