仕上げる事があります。 &内部または間のすべての項目を#に置き換える必要があります<ex>
</ex>
。実際の例は次のとおりです。
a & b & c <ex> a & b & c </ex> a & b & c
<ex>
繰り返しますが、&内部と以前のすべての項目を置き換える必要があります。</ex>
予想出力:
a & b & c <ex> a # b # c </ex> a & b & c
これを行う方法の説明を投稿してください。
編集#1
sed
AS400システムで実行する予定なので、Perlや他のインタプリタをインストールできないので、ソリューションを提供してください。
答え1
<ex>...</ex>
各行が一度だけ表示される場合:
sed -e :1 -e 's@\(<ex>.*\)&\(.*</ex>\)@\1#\2@;t1'
複数の項目がある可能性があり、入れ子になっていない場合(または入れ子になって&
最も深い項目のみを置き換えたい場合):
sed '
s|_|_u|g # replace all underscores with "_u"
s|(|_o|g # replace all open parentheses with "_o"
s|)|_c|g # replace all close parentheses with "_c"
s|<ex>|(|g # replace all open ex tags with "("
s|</ex>|)|g # replace all close ex tags with ")"
:1 # a label
s/\(([^()]*\)&\([^()]*)\)/\1#\2/g
# find:
# an open parentheses,
# some non-parentheses chars (captured),
# an ampersand,
# some non-parentheses chars (captured) and
# a close parentheses,
# replace with
# the first captured text,
# an octothorpe
# the second captured text,
# globally in the current record.
t1 # if there was a successful replacement, goto label "1",
# else carry on
s|(|<ex>|g # restore open tags
s|)|</ex>|g # restore close tags
s|_o|(|g # restore open parentheses
s|_c|)|g # restore close parentheses
s|_u|_|g # restore underscores
'
入れ子にすることができ、それを囲むものに置き換えたい場合:
sed '
s|_|_u|g;s|(|_o|g;s|)|_c|g
s|<ex>|(|g;s|</ex>|)|g;:1
s/\(([^()]*\)(\([^()]*\))\([^()]*)\)/\1_O\2_C\3/g;t1
:2
s/\(([^()]*\)&\([^()]*)\)/\1#\2/g;t2
s|(|<ex>|g;s|)|</ex>|g
s|_O|<ex>|g;s|_C|</ex>|g
s|_o|(|g;s|_c|)|g;s|_u|_|g'
答え2
Perl(バージョン5.14が必要)を使用して、次の操作を行います。
perl -pe 's%(<ex>.*?</ex>)% $1 =~ s/&/#/gr %eg'
以前のバージョンでは、より冗長でなければなりませんでした。
perl -pe 's%(<ex>.*?</ex>)% ($_x = $1) =~ s/&/#/g; $_x %eg'
説明:<ex>
タグ間のすべての内容をに入れて$1
&$1
を#に置き換えます。
答え3
別のPerlコマンド、
$ perl -pe 's/&(?=(?:(?!<ex>|<\/ex>).)*<\/ex>)/#/g' file
a & b & c <ex> a # b # c </ex> a & b & c
上記のコマンドを説明する前に、Negative LookaheadとPositive Lookaheadが実際に何をしているかを説明します。
正規表現は(?=...)
肯定的な予測を意味します。ツアー(たとえば、肯定的および否定的なプレビュー、肯定的および否定的なプレビュー)は、幅がゼロの一致を作成します。つまり、どの文字とも一致しません。通常、肯定的および否定的な予測は、ヘルスチェックの目的で使用されます。(?:...)
非キャプチャグループとも呼ばれます。つまり、非キャプチャグループ内のパターンのみが一致します。どの文字もキャプチャしません。
(?!<ex>|<\/ex>)
文字列<ex>
または.と一致できません</ex>
。(?:(?!<ex>|<\/ex>).)
実際に意味するのは、最初に次の3〜4文字を見つけ、次の3〜4文字が不可能かどうかを確認する<ex>
ことです</ex>
。.
この条件が満たされると、次の文字のみが一致します。(?:(?!<ex>|<\/ex>).)*
文字列<ex>
またはが検出されるまで、上記の手順を0回以上実行します。</ex>
これら 2 つの文字列のいずれかが見つかると、突然次の文字の一致が停止します。(?:(?!<ex>|<\/ex>).)*<\/ex>
次の</ex>
文字列とも一致します。これはすべて予測に反映されます。&(?=(?:(?!<ex>|<\/ex>).)*<\/ex>)
&
最後に、上記の条件を満たす文字が次の場合にのみ文字と一致します。つまり、&
次に属さない文字が来るか、閉じるマークが0回以上来なければ<ex>
なりません。</ex>
</ex>
答え4
入れ子になっていない行で複数回発生すると役に立ちます。
#cat plop
>a & b & c <ex> a & b & c </ex> a & b & c <ex> a & b & c </ex> a & b & c
#cat plop |sed -e :1 -e 's@\(<ex>[^(</ex>)]*\)&\(.*</ex>\)@\1+\2@;t1'
>a & b & c <ex> a + b + c </ex> a & b & c <ex> a + b + c </ex> a & b & c