2

次の形式のテキストファイルがあります

[Section1]
property1 = value1
property2 = value2

[Section2]
property1 = value1
property2 = value2

[Section foo]
foo = 1
bar = "whatever"

そのように正規表現を使用して各行にセクションのタイトルを追加する方法はありますか

Section1: property1 = value1
Section1: property2 = value2

Section2: property1 = value1
Section2: property2 = value2

アップデート

プログラミング言語やツールは含めなかったので、可能性のリストを以下に示します

  1. JavaScript
  2. パール
  3. VIM

非正規表現を含む他の提案を受け入れます。

4

6 に答える 6

3

はい、できます。まず、次の正規表現をキャプチャする必要があります

\[(Section\d+)\]\n(.+?\n)|(?:.*?\n)\[Section\d+\]

セクション ラベルと、それを適用するすべての行をキャプチャする必要があります。その後、単純な攪拌連結にする必要があります

正規表現

()     : a capturing group  
(?:..) : non-capturing group  
\d+    : 1 or more digits  
.+?\n  : 1 or more characters and newline(the '?' means it's non-greedy)  
.*?\n  : 0 or more characters and newline
于 2013-01-07T16:13:10.447 に答える
2

これが Vim ソリューションです — ファイルを開いて次のコマンドを実行するだけです:

:g/^\[.*\]$/ s/^\[// | s/\]$/:/ | d | ,/\n$/ normal PJ

これにより、セクションの見出し行が選択され、そのセクション内の他の行の前に付けるために各行が目的の形式に変換され、見出し行が削除され、セクション内の他のすべての行の先頭に挿入されます。

詳細に:

  • :g//パターンに一致するファイル内の行を選択し、次のコマンドをそれぞれに適用します。この場合、パターンは begin[と endの行に一致します]
  • 1つ目:s///はオープニング[を削除し、2 つ目はクロージング]を に変更し:ます。行を結合する (以下を参照) ことで追加できるため、末尾にスペースを追加する必要はありません。
  • |複数のコマンドを分離し:、最初の の範囲内でいくつかのアクションを許可します:g//
  • :d行を削除します。これは、貼り付け可能な場所からレジスタにも格納されます。これは、現在の行がセクションの最初のプロパティ行であることを意味します。
  • プレフィックスは、セクション内のすべての行に追加する必要があります。,範囲を定義します。
  • 範囲の開始は現在の行です。これがデフォルトであるため、. の前に何かを付ける必要はありません,
  • 範囲の最後の行は、空白行 (またはファイルの終わり) の直前の行です。これには、範囲の終わりと見なされている行の後の行を調べる必要があります。はそれ\nを行い、行末の改行文字に一致させ、それを過ぎたパターンを次の行 (存在する場合) に移動します。そのポイントが と一致する行末である場合、$( の直後に別の行末があるため) 空白行が続く必要があります。そうしない\nと、ファイルの末尾になります。
  • したがって,/\n$/、プレフィックスが必要な行の範囲を定義します。
  • :put!最近削除された行を現在の行の上に挿入し、挿入したばかりの行を現在の:join行にし、その行を次の行と結合して、それらの間にスペースを挿入します。範囲内の各行に対してこれを行います。
  • ただし:put、範囲は取りません。行だけです。通常、範囲内の各行にコマンドを適用するには、:g//. しかし、ここではすでに:g//コマンドの中にあり、ネストすることはできません。
  • 幸いなこと:normalに、指定された通常モードのキーストロークが範囲内の各行に適用されます。Pノーマルノーマルモードで押すのは:put!コマンドとJ同じで、 と同じ:joinです。
  • したがって,/\n$/ normal PJ、現在の行から空白行 (またはファイルの最後) の前の行までの各行に対して、最近削除されたプレフィックスをその上に貼り付け、既存の行をプレフィックスの最後に結合します。
  • :normal|コマンドセパレータではなく通常モードのキーストロークとして解釈されるため、別のコマンドを続けることはできません。したがって、一般:normalに、コマンド シーケンスで使用するには、 でラップする必要があり:exeます。しかし、この場合:normalは、最後にやりたいことなので、コマンドの最後にそのままにしておくことができます。
  • 上記で最初のセクションが変換されると、Vim は に一致する 2 番目のセクションの見出しに移動し、:g//もう一度実行します。
于 2013-01-08T10:40:38.650 に答える
1

これはワンライナーで行うことができます:

perl -F"\n" -00 -anwE '$h = shift @F; 
                       $h =~ s/^\[|\]$//g; 
                       say "$h: $_" for @F; 
                       say $/;' paragraph.txt

このコードでは、段落モードを使用してファイルから行のブロックを読み取り、各ブロックを改行で自動分割し、ブロックの最初の行を削除してクリーンアップし、結果の印刷 ( say) のヘッダーとして使用します。

  • -00入力レコード区切りを空の文字列に設定して、段落モードを有効にします。つまり、次の二重改行まで読み上げます。
  • -a入力の各行を自動分割@F
  • -Fスイッチを使用すると、自動分割の区切り文字として改行を設定できます
  • -Eのよう-eに機能しますが、次のような機能を有効にしますsay

コードはスクリプト形式で次のようになります。

use warnings;
use strict;

$/ = "";                      # paragraph mode, read until "\n\n"
use feature 'say';            # enable 'say'
while (<>) {                 
    my @F = split /\n/;       
    my $h = shift @F;         
    $h =~ s/^\[|\]$//g;       # clean up lines
    say "$h: $_" for @F;      
    say $/;                   # print paragraph ending 
}
于 2013-01-07T16:59:22.947 に答える
0

この正規表現は、 group の値をキャプチャします。

\[(?<Section>.*?)\]\r\n(?<p1>property\d)\s=\s(?<v1>value\d)\r\n(?<p2>property\d)\s=\s(?<v2>value\d)

これは、前のキャプチャを置き換えるために使用されます。

${Section} : ${p1} = ${v1} 
${Section} : ${p2} = ${v2}

Expresso ツールの結果は次のとおりです。

セクション 1 : プロパティ
1 = 値 1 セクション 1 : プロパティ 2 = 値 2

セクション
2 : プロパティ 1 = 値 1 セクション 2 : プロパティ 2 = 値 2

これを最適化して汎用にする必要があります

于 2013-01-07T16:47:30.887 に答える
0

を使用してコマンドラインから実行される別のオプションを次に示しますperl <scriptName> <dataFile>

use warnings;
use strict;

my $section;
while (<>) {
    if (/^\[(Section[^\]]*)\]$/) {
        $section = $1;
        next;
    }
    print /\S/ ? "$section: $_" : $_;
}
于 2013-01-07T17:54:40.270 に答える
0

この Perl ワンライナーの行に沿って何かを試してください:

perl -n -wE 'if (/^\[(\w+)\]$/) { $section = $1; } else { s/^(?=\S)/$section: /; print; }' yourfile.txt

make は、一度にファイルの各行-nを処理します。perl行がセクションの見出しのように見える場合は、後で使用するためにセクション名が保存されます。それ以外の場合は、以前に保存されたセクション名を印刷可能な文字で始まる行に追加し、その行を印刷します。

于 2013-01-07T16:49:33.090 に答える