次のパターンに従ってファイルの文字列を変更したいと思います。
<<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つずつ交換してください。
- 新しい交換が完了しなくなるまでこの操作を繰り返します。
- ジャンクを外してください。
このように:
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 start
s
交換したばかりのタグに移動してください。- …
<<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 …>>
同じ行にある複数のフラグメント間の一致を防ぎます。