Sed - 2つの文字列を置き換えながらその間の内容を保持する方法は?

Sed - 2つの文字列を置き換えながらその間の内容を保持する方法は?

一部のDokuWikiページをMediaWiki形式に変換するシェルスクリプトを作成しています。その逆に。脚注に問題があります。

DokuWikiには、DokuWikiのデフォルトの脚注マークアップに拡張機能を追加するプラグインがあります。そのうちの1つは、メモに名前を追加して後で再利用できる機能です。たとえば、

徳ウィキ メディアウィキ
[(FOO>This is a footnote.)] <ref name="FOO">This is a footnote.</ref>
[(BAR>Another note in the same paragraph.)] <ref name="BAR">Another note in the same paragraph.</ref>

そしてsed簡単に見つけて交換できます。 "コメント名"を持つ脚注に関連する私のスクリプトコマンドは次のとおりです。

sed -ri 's@\[\(.*>@<ref name=\"XXX\">@g' dokuwiki-page.txt
sed -ri 's@\)\]@<\/ref>@g' dokuwiki-page.txt

ただし、もちろん名前は保持されず、その名前を持つすべてのコメントに新しい一般コメント名「XXX」を適用するだけです。したがって、上記の例では、結果は次のようになります。

徳ウィキ メディアウィキ
[(FOO>This is a footnote.)] <ref name="XXX">This is a footnote.</ref>
[(BAR>Another note in the same paragraph.)] <ref name="XXX">Another note in the same paragraph.</ref>

コメント名(例ではFOOとBAR)を維持するのに役立ちます。私は他の解決策を受け入れるだけではありません。sed

重要事項:

  1. 脚注文は段落の途中に表示され、脚注名を含む複数の参照は同じ段落に異なる名前で表示されることがあります。 (別名Unixの「非常に長い行」の段落)
  2. MediaWikiマークアップはHTMLタグ(sumsでいっぱい)が多すぎるため、コマンドを分割して最初のコマンドから置き換え、2番目のコマンドで[(置き換えることはできません。タグが誤って交換された可能性があります。><>
  3. 内部[(...)]がないものもあります。代わりに>inのようです。[(This is a nameless note.)][(My_Note_Name>This is a named note.)]

ベストアンサー1

perl貪欲ではない反復演算子で正規表現を使用すると、この種の操作ははるかに簡単です。

perl -i -pe 's{\[\((.*?)>(.*?)\)\]}{<ref name="$1">$2</ref>}g' your-file

-iとは-r非標準sedオプションです。-i実際にはperl互いに互換性のない方法ですが、いくつかの実装によってコピーされます。

perl複数sedの実装とは異なり、行のサイズに制限はなく、NUL文字を処理でき、デフォルトでは入力をバイト単位で処理するため、ユーザーのロケールからテキストにデコードできない入力の問題はありません。

入力の一部にが[(...)]含まれていない可能性がある場合は、正規表現を調整する必要が>あります。参照ラベルにword文字(ASCII番号と下線)のみが含まれている場合は、次のようになります。

perl -i -pe 's{\[\((\w+)>(.*?)\)\]}{<ref name="$1">$2</ref>}g' your-file

別の方法は、すべての項目を見つけて[(...)]別のステップに置き換えることです。

perl -i -pe '
  s{\[\(.*?\)\]}{
    $& =~ s{\[\((.*?)>(.*)\)\]}{<ref name="$1">$2</ref>}r
  }ge' your-file

また、以下を使用して名前のないコメントを変更することもできます<ref>nameless</ref>

perl -i -pe '
  s{\[\(.*?\)\]}{
    $& =~ s{\[\((?:(.*?)>)?(.*)\)\]}{
      "<ref" . (defined($1) ? qq( name="$1") : "") . ">$2</ref>"
    }re
  }ge' your-file

[(...)]または、含まれていないものと一致することを確認するには、否定予測演算子を使用してください)]

perl -i -pe 's{\[\(((?:(?!\)\]).)*?)>((?1))\)\]}{<ref name="$1">$2</ref>}g' your-file

おすすめ記事