我有一个包含这样的行的文件
some thing <phrase>a phrase</phrase> some thing else <phrase>other stuff</phrase>
我需要用下划线替换<phrase>
标记之间的所有空格。因此,基本上我需要用下划线替换介于>
和</
之间的所有空格。我已经在sed,awk和perl中尝试了许多不同的命令,但是还无法使任何东西正常工作。以下是我尝试过的一些命令。
sed 's@>\s+[</]@_@g'
perl -pe 'sub c{$s=shift;$s=~s/ /_/g;$s}s/>.*?[<\/]/c$&/ge'
sed 's@\(\[>^[<\/]]*\)\s+@\1_@g'
awk -v RS='\\[>^[<\]/]*\\]' '{ gsub(/\<(\s+)\>/, "_", RT); printf "%s%s", $0, RT }' infile
我一直在研究这两个问题,试图修改答案以使用所需的字符。
sed substitute whitespace for dash only between specific character patterns
有人可以帮忙吗?
答案 0 :(得分:5)
不要使用正则表达式来解析XML / HTML。
use warnings;
use 5.014; # for /r modifier
use Mojo::DOM;
my $text = <<'ENDTEXT';
some thing <phrase>a phrase</phrase> some thing else <phrase>other stuff</phrase>
ENDTEXT
my $dom = Mojo::DOM->new($text);
$dom->find('phrase')->each(sub { $_->content( $_->content=~tr/ /_/r ) });
print $dom;
输出:
some thing <phrase>a_phrase</phrase> some thing else <phrase>other_stuff</phrase>
更新: Mojolicious甚至包含一些糖,可以将代码粉碎成一个单行纸:
$ perl -Mojo -pe '($_=x($_))->find("phrase")->each(sub{$_->content($_->content=~tr/ /_/r)})' input.txt
答案 1 :(得分:2)
我需要用下划线替换介于
>
和</
之间的所有空格。
那实际上不会做你想要的,因为在
some thing <phrase>a phrase</phrase> some thing else <phrase>other stuff</phrase>
^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
“ >
和</
之间的子字符串覆盖的范围超出了您的想象(上面标记为^
)。
我认为用Perl表达需求的最直接方法是
perl -pe 's{>[^<>]*</}{ $& =~ tr/ /_/r }eg'
此处[^<>]
用于确保匹配的子字符串不能包含<
或>
(尤其是它不能匹配其他<phrase>
标记)。
如果这太可读了,您也可以这样做
perl '-pes;>[^<>]*</;$&=~y> >_>r;eg'
答案 2 :(得分:2)
这可能对您有用(GNU sed):
sed -E 's/<phrase>|<\/phrase>/\n&/g;ta;:a;s/^([^\n]*(\n[^\n ]*\n[^\n]*)*\n[^\n]*) /\1_/;ta;s/\n//g' file
通过插入换行符来分隔标签。用下划线迭代替换成对的换行之间的空格。如果没有其他匹配项,请删除引入的换行符。
答案 3 :(得分:1)
另一个Perl,在<phrase>
标签之间替换
$ export a="some thing <phrase>a phrase</phrase> some thing else <phrase>other stuff</phrase>"
$ echo $a | perl -lne ' s/(?<=<phrase>)(.+?)(?=<\/phrase>)/$x=$1;$x=~s{ }{_}g;sprintf("%s",$x)/ge ; print '
some thing <phrase>a_phrase</phrase> some thing else <phrase>other_stuff</phrase>
$
编辑
感谢@haukex,进一步缩短
$ echo $a | perl -lne ' s/(?<=<phrase>)(.+?)(?=<\/phrase>)/$x=$1;$x=~s{ }{_}g;$x/ge ; print '
some thing <phrase>a_phrase</phrase> some thing else <phrase>other_stuff</phrase>
$
答案 4 :(得分:1)
使用GNU awk进行多字符RS和RT:
$ awk -v RS='</?phrase>' '!(NR%2){gsub(/\s+/,"_")} {ORS=RT}1' file
some thing <phrase>a_phrase</phrase> some thing else <phrase>other_stuff</phrase>
答案 5 :(得分:1)
如果您是gnu sed在“ d”中的数据;
sed -E ':b s/<(\w+)>([^<]*)\s([^<]*)(<\/\1)/<\1>\2_\3\4/;tb' d