正規表現:どれだけ知らずに、一致するすべてのグループを引用します。

正規表現:どれだけ知らずに、一致するすべてのグループを引用します。

次のパターンに従ってファイルの文字列を変更したいと思います。

  • <<key q>><kbd>q</kbd>
  • <<key Ctrl q>><kbd>Ctrl</kbd>+<kbd>q</kbd>
  • <<key Ctrl Shift Alt q>><kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>Alt</kbd>+<kbd>q</kbd>

更新:ファイルには追加のテキストも含まれています。例: Press <<key Ctrl q>> to quit.

この問題を解決するために見つけることができる最善の解決策は、sed呼び出す1、2、3、4キーに別々のスクリプトを使用することです。

sed -i -E \
    -e 's|<<key ([^ ]+)>>|<kbd>\1</kbd>|g'
    -e 's|<<key ([^ ]+) ([^ ]+)>>|<kbd>\1</kbd>+<kbd>\2</kbd>|g' \
    -e 's|<<key ([^ ]+) ([^ ]+) ([^ ]+)>>|<kbd>\1</kbd>+<kbd>\2</kbd>+<kbd>\3</kbd>|g' \
    -e 's|<<key ([^ ]+) ([^ ]+) ([^ ]+) ([^ ]+)>>|<kbd>\1</kbd>+<kbd>\2</kbd>+<kbd>\3</kbd>+<kbd>\4</kbd>|g' \
    file.txt

明らかに、これは5つ以上のキーを含むマクロでは失敗します。

より一般的な解決策はありますか?Nキー?に限定されず、構造的正規sed表現(sregx)しかし、それを行う方法が見つかりません。

答え1

私はそのようなタスクを実行するためにPerlを使用します。

#!/bin/perl
while(<>) {
    if (/<<key (.*?)>>/) {
        my $pattern_with_keys = $1;
        my @keys = split / /, $pattern_with_keys ;
        my @kbd_keys = map {"<kbd>$_</kbd>"} @keys;
        print join('+', @kbd_keys), "\n";
    }
}

それを実行しperl script.pl < source_file.txtてお楽しみください。

答え2

  1. 一度に1つずつ交換してください。
  2. 新しい交換が完了しなくなるまでこの操作を繰り返します。
  3. ジャンクを外してください。

このように:

sed -E ':start s|(<<key[^>]*) ([^>]*)>>|\1>>+<kbd>\2</kbd>|g; t start; s|<<key>>\+||g'

どこ:

  • :startラベルです。
  • s|(<<key[^>]*) ([^>]*)>>|\1>>+<kbd>\2</kbd>|gになる<<key Ctrl Shift Alt q>><<key Ctrl Shift Alt>>+<kbd>q</kbd>
  • t starts交換したばかりのタグに移動してください。
  • <<key Ctrl Shift Alt>>+<kbd>q</kbd>となって
    <<key Ctrl Shift>>+<kbd>Alt</kbd>+<kbd>q</kbd>、それでは
    <<key Ctrl>>+<kbd>Shift</kbd>+<kbd>Alt</kbd>+<kbd>q</kbd>ついに
    <<key>>+<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>Alt</kbd>+<kbd>q</kbd>。次の反復ではs何も置き換えられないため(<<key>>スペースがないため一致しません)、操作tは不要です。
  • s|<<key>>\+||g残留物を取り除きます。

注:([^>]*.*)は、<<key …>>同じ行にある複数のフラグメント間の一致を防ぎます。

関連情報