最初的問題
...
<div>
<ul>
<li><FormattedMessage id='some.language.key_1' defaultMessage='Some message 1' /></li>
<li><FormattedMessage id='some.language.key_2' defaultMessage='Some message 2' /></li>
<li><FormattedMessage id='some.language.key_3' defaultMessage='Some message 3' /></li>
</ul>
</div>
<div>
<p>Some other contents</p>
</div>
...
我想產生一個包含<FormattedMessage>
資料夾中所有標籤的檔案。輸出應如下所示:
...
<FormattedMessage id='some.language.key_1' defaultMessage='Some message 1' />
<FormattedMessage id='some.language.key_2' defaultMessage='Some message 2' />
<FormattedMessage id='some.language.key_3' defaultMessage='Some message 3' />
...
我知道我可以使用這個命令來獲得合理的結果:
grep -REho '<FormattedMessage .*\/>' my/target/folder/.
我目前的問題
當一些實際結果如下所示時,事情會變得複雜:
<FormattedMessage id='some.lang.key_1' defaultMessage="Hello {myvar}" values={{ myvar: <FormattedMessage id='some.lang.key_2' defaultMessage='World' /> }} />} />
我想為這種模式產生 2 條單獨的線:
<FormattedMessage id='some.lang.key_1' defaultMessage="Hello {myvar}" values={{ myvar: <FormattedMessage id='some.lang.key_2' defaultMessage='World' /> }} />} />
<FormattedMessage id='some.lang.key_2' defaultMessage='World' />
無論如何,我可以用一些 Unix 命令魔法來做到這一點嗎?
更新:一個更合理的範例文件:
<ul>
<li><FormattedMessage id='lang.key_1' defaultMessage='Message 1' /></li>
<li><FormattedMessage id='lang.key_2' defaultMessage='Message 2' /></li>
<li><FormattedMessage id='lang.key_3' defaultMessage='Message 3' /></li>
<li><FormattedMessage id='lang.key_4' defaultMessage='Message 4' /></li>
<li><FormattedMessage id='lang.key_5' defaultMessage="Message 5 with {inner}" values={{ inner: <Link><FormattedMessage id='lang.key_6' defaultMessage='Message 6' /></Link> }} /></li>
<li><FormattedMessage id='lang.key_7' defaultMessage='Message 7' /></li>
</ul>
期望的輸出:
<FormattedMessage id='lang.key_1' defaultMessage='Message 1' />
<FormattedMessage id='lang.key_2' defaultMessage='Message 2' />
<FormattedMessage id='lang.key_3' defaultMessage='Message 3' />
<FormattedMessage id='lang.key_4' defaultMessage='Message 4' />
<FormattedMessage id='lang.key_5' defaultMessage="Message 5 with {inner}" values={{ inner: <Link><FormattedMessage id='lang.key_6' defaultMessage='Message 6' /></Link> }} />} /></li>
<FormattedMessage id='lang.key_6' defaultMessage='Message 6' />
<FormattedMessage id='lang.key_7' defaultMessage='Message 7' />
答案1
您的問題很容易解決,recursive regexes
因為一個模式多次包含在同一個模式中。
perl -lane '
$. == 1 and $re = qr{
( # capturing group start
<FormattedMessage\s # match tag opening
(?:
(?>[^<>])+ # consume as many non-angle brackets as is possible
|
(?1) # otherwise, recurse
|
(?>.*?>) # skip a noninteresting tag
)*
/> # match tag closing
) # capturing group end
}x;
next unless /<FormattedMessage\s/;
while ( my @tags = /$re/g ) {
print for @tags;
$_ = join $,, map { s/^<(.*)>$/$1/r } @tags;
}
' file1
結果
<FormattedMessage id='lang.key_1' defaultMessage='Message 1' />
<FormattedMessage id='lang.key_2' defaultMessage='Message 2' />
<FormattedMessage id='lang.key_3' defaultMessage='Message 3' />
<FormattedMessage id='lang.key_4' defaultMessage='Message 4' />
<FormattedMessage id='lang.key_5' defaultMessage="Message 5 with {inner}" values={{ inner: <Link><FormattedMessage id='lang.key_6' defaultMessage='Message 6' /></Link> }} />
<FormattedMessage id='lang.key_6' defaultMessage='Message 6' />
<FormattedMessage id='lang.key_7' defaultMessage='Message 7' />
答案2
將輸出從第一個傳遞grep
到sed
:
sed -n 'p;s,..*\(<FormattedMessage[^>]*>\).*,\1,p'
輸出:
$ grep -REho '<FormattedMessage .*\/>' file | sed -n 'p;s,..*\(<FormattedMessage[^>]*>\).*,\1,p'
<FormattedMessage id='lang.key_1' defaultMessage='Message 1' />
<FormattedMessage id='lang.key_2' defaultMessage='Message 2' />
<FormattedMessage id='lang.key_3' defaultMessage='Message 3' />
<FormattedMessage id='lang.key_4' defaultMessage='Message 4' />
<FormattedMessage id='lang.key_5' defaultMessage="Message 5 with {inner}" values={{ inner: <Link><FormattedMessage id='lang.key_6' defaultMessage='Message 6' /></Link> }} />
<FormattedMessage id='lang.key_6' defaultMessage='Message 6' />
<FormattedMessage id='lang.key_7' defaultMessage='Message 7' />