2

以前は、単純な文字列の行を繰り返し処理していました

for line in s:gmatch("[^\r\n]+") do

そしてそれは完璧に機能しました!その後、実際の生活が起こりました...。

....そして今私の要件が変更されました:私も空の行に一致する必要があります。そして、ここに問題があります。この形式の反復は、それ自体がすべてジャングルであるいくつかの場所で使用されるため、周囲のコードをできるだけ変更しないようにします。上記の関数が一致しなかったという微妙な期待のため、これまでのところgmatch/を使用した私の試みでは、上記のパターンの「ドロップイン」置換を作成できませんでした。find

私が探している構成(for line in some_matcher(s) do)は、私が心配しているすべてのエッジケースをカバーすると私が信じている次の要件に一致します。

   INPUT            EXPECTATIONS

1. ''            -- match once   ('')
2. '\r\n'        -- match twice  ('', '')
3. '\r\n\r\n'    -- match thrice ('', '', '')
4. 'aaa'         -- match once   ('aaa')
5. 'aaa\r\n'     -- match twice  ('aaa', '')
6. 'aaa\r\nbbb'  -- match twice  ('aaa', 'bbb')
7. '\r\nbbb'     -- match twice  ('', 'bbb')

\r\n私の古いソリューションは、行末のみが発生することを前提としています。新しいソリューションがそのシナリオのみを処理する場合は、まったく問題ありません。

しかし、私の店ではLinuxサポートの計画についての話があるので、よりわかりやすい行末(将来のUNIX互換性のため)も扱う回答をいただければ幸いです。\n数か月後にこの問題を再検討する必要はありません。 。ただし、多くの場合、元の文字列入力にこの一致の開始列が必要です。上記の構成(for ... do)が追加の利点としてそれを出力できる場合、それは特に素晴らしいでしょう。

4

1 に答える 1

2

クロスプラットフォームの方法で改行境界をスキップ/破棄するのではなく正確に検出する必要がある場合は、との両方を含むセットを使用することはできません\r\nこれは、改行シーケンス\r\nが1回ではなく2回一致するためです(CRLFは単一の改行です)。 DOS / Windowsの場合)。これは、十分に強力な正規表現エンジン(代替のサポートなど)で処理できますが、Luaのパターンマッチングライブラリはごくわずかです。

最善の策は、テキストを処理する前に改行を正規化することです。次のようになります。

function normalize_eols(s)
    return s
        :gsub('\r\n','\n')
        :gsub('\r', '\n')
end

input => output gridに関しては、改行を行区切り文字と考えると、[^\n]*(0個以上の非改行文字)が機能すると予想されますが、次のようになります。

''         => ('')
'\n'       => ('', '')
'\n\n'     => ('', '', '')
'aaa'      => ('aaa', '')
'aaa\n'    => ('aaa', '', '')
'aaa\nbbb' => ('aaa', '', 'bbb', '')
'\nbbb'    => ('', 'bbb', '')

率直に言って、理由はわかりません。

ただし、改行を行末記号と考えると、入力に改行を追加し、パターン(0個以上の非改行文字の後に改行が続く)を使用することで、必要な結果を得ることができます。[^\n]*\n

'\n'         => ('')
'\n\n'       => ('', '')
'\n\n\n'     => ('', '', '')
'aaa\n'      => ('aaa')
'aaa\n\n'    => ('aaa', '')
'aaa\nbbb\n' => ('aaa', 'bbb')
'\nbbb\n'    => ('', 'bbb')

したがって、コードは次のように変更されます。

s = normalize_eols(s) .. '\n'
for line in s:gmatch('([^\n]*)\n') do
    ...
于 2012-05-02T19:53:24.207 に答える