2016-12-02 4 views
4
my $str = "<SampleElement oldattribs=\"sa1 sa2 sa3\">"; 

$str =~ s#<SampleElement[^>]*oldattribs="([^"]*)"# 
      my $fulcnt=$&; 
      my $afids=$1; 
      my @affs =(); 
      if($afids =~ m/\s+/) { 
       @affs = split /\s/, $afids; 
       my $jnafs = join ",", map { $_=~s/[a-z]*//i, } @affs; 
       ($fulcnt." newattribs=\"$jnafs\""); 
      } 
      else { 
       ($fulcnt); 
      } 
     #eg; 

私の出力を作成するためのPerlを使用してマップ:が参加し、分割して、新しいはattribsに

<SampleElement oldattribs="sa1 sa2 sa3" newattribs="1,1,1"> 

予想される出力を:私が間違っているのどこ

<SampleElement oldattribs="sa1 sa2 sa3" newattribs="1,2,3"> 

誰かが私を指摘することができます。前もって感謝します。

+4

[XML/HTML](http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454)を次のように解析しないでください。代わりに[XML](http://search.cpan.org/~mirod/XML-Twig/Twig.pm)パーサーを使用してください。 – dgw

+3

ワンライナー:[ '$ STR =〜S {] * oldattribs = "\ K(? [^"] +)} [ "の$ + {V} \" newattribs = \」 " $ + {v} =〜s!\ pL *(? \ d +)$ | \ pL *(? \ d +)\ s *! $ + {f}? $ + {f}:$ + {s}。 "、"!egr] e; '](https://ideone.com/KwEapL)。 –

答えて

2

ここには、入力$strからの出力を簡単に作成する方法があります。

注:入力は二重ではなく、一重引用符で囲みます。その後、\"は正規表現の問題ではありません。

my $str = '<SampleElement oldattribs=\"sa1 sa2 sa3\">'; 

# Pull 'sa1 sa2 sa3' string out of it 
my ($attrs) = $str =~ /=\\"([^\\]+)/; # " # (turn off bad syntax highlight) 

# Build '1,2,3' string from it 
my $indices = join ',', map { /(\d+)/ } split ' ', $attrs; 

# Extract content between < > so to add to it, put it back together 
my ($content) = $str =~ /<(.*)>/;  
my $outout = '<' . $content . " newattribs=\"$indices\"" . '>'; 

これにより、必要な出力が得られます。

これらの中には、単一のステートメントに結合するものもあります。例

my $indices = 
    join ',', map { /(\d+)/ } split ' ', ($str =~ /"([^\\]+)/)[0]; # " 

$str =~ s/<(.*)>/<$1 newattribs=\"$indices\">/; 

については、こののすべてが 1つの正規表現にロールバックすることができますが、それだけで扱いにくく、維持するのが困難となります。すべて–上記


これはただのスニペットや二つは文字通り存在しない限り、手でそれをしないでください... XMLかなように見えます。優れたパーサがあります。

1
マップ検索機能により、この上

見つかりソリューション:私は私のコードに以下の行を更新した

my $str = "<SampleElement oldattribs=\"sa1 sa2 sa3\">"; 

$str=~s#<SampleElement[^>]*oldattribs="([^"]*)"#my $fulcnt=$&; my $afids=$1; 
my @affs =(); 
if($afids=~m/\s+/) 
{ 
    @affs = split /\s/, $afids; 
    my @newas = join ",", map { (my $foo = $_) =~ s/[a-z]*//i; $foo; } @affs ; 
    ($fulcnt." newattribs=\"@newas\""); 
} 
else 
{ 
    ($fulcnt); 
} 
#eg; 

my @newas = join ",", map { (my $foo = $_) =~ s/[a-z]*//i; $foo; } @affs ; 

代わりの

my $jnafs = join ",", map { $_=~s/[a-z]*//i, } @affs; 

そのおかげさまですべてのために。

+0

変数 '$ foo'は必要ありません。' map {s/[a-z] * // i;あなたも、良いことだ 'マップ{S/[AZ] * // IR}' – dgw

+2

- あなたの代わりに数字が一致しないことができ、'マップ{/(\ d +)/} '(私の答えを見てください)?また、これは確かに事を逃す - 正規表現の行が構文賢明(それは動作しません)が壊れています。作業コードを掲載されるように修正していただけますか? – dgw

+1

を使用しますが、なぜ手紙を取り除くことができperlの5.14以来$ _} ' – zdim

4

あなたが間違っているのは、あなたが思っているよりも早く、正規表現を使ってXMLを解析しているところです。 XMLは文脈で、正規表現ではありません、so it's NEVER going to be better than a dirty hack.

#!/usr/bin/env perl 
use strict; 
use warnings; 

use XML::Twig; 
my $twig = XML::Twig -> parse (\*DATA); 

my $sample_elt = $twig -> get_xpath('//SampleElement',0); 
my @old_att = split (' ', $sample_elt -> att('oldattribs')); 
$sample_elt -> set_att('newattribs', join " ", map { /(\d+)/ } @old_att); 

$twig -> set_pretty_print ('indented_a'); 
$twig -> print; 


__DATA__ 
<XML> 
    <SampleElement oldattribs="sa1 sa2 sa3"> 
    </SampleElement> 
</XML> 

しかし、あなたの問題の核心に答えるために - あなたはここでイテレータとしてmapを悪用しています。

map { $_=~s/[a-z]*//i, } @affs; 

ので何こと@affs内のすべての要素を反復処理し、それらの変更...しかしmapだけで式の結果を返すされているやっている - それは働いていたので1です。

あなたはが@affsにあなたを思い変更したい場合:

s/[a-z]*//i for @affs; 

しかし、あなたはは、その後、簡単な答えはr正規表現フラグを使用することですしたくなかった場合:

map { s/[a-z]*//ir } @affs; 

または私の例で行ったように:

map { /(\d+)/ } @affs; 
試合はRegex文字列の数字の一部をキャプチャしますが、結果として「捕獲」のテキストが返されているものである

関連する問題