0

サブパターン プレースホルダー '$1' を変数の置換演算子 's///' に渡すときに、正しくクォートできない問題があります。誰かがこれに光を当てて、私が間違っていることを教えてもらえますか?

MS Word ドキュメントのセットを HTML ファイルにエクスポートしています。これは、ファイルに多くの相互参照が含まれており、機能し続けるにはこれらを修正する必要があることを除いて、多かれ少なかれ問題なく機能します。エクスポートされた参照は 'href="../../somefilename.docx"' の形式であり、元の Word ファイルの代わりにエクスポートされた html ファイルを参照するには、これらを 'href="somefilename.htm"' に変更する必要があります。 .

たとえば、ファイル test.htm の例は次のようになります。

<html>
<body>
<a href="../../filename1.docx" />
<a href="../../filename2.docx" />
<a href="../../filename3.docx" />
<a href="../../filename4.docx" />
</body>
</html>

プログラムの実行により、次の結果が得られます。

<html>
<body>
<a href="filename1.htm" />
<a href="filename2.htm" />
<a href="filename3.htm" />
<a href="filename4.htm" />
</body>
</html>

その仕事をするために、小さな Perl プログラム 'ReplaceURLs' を書きました。パターンと置換式を「ハードコード」すると (つまり、パターンを s/.../.../g ステートメントに直接配置すると)、正常に動作します - バリアント 1 を参照してください。これらの式を引数 (つまり、s/$pattern/$subst/g) として渡せるようにしたいのですが、うまくいきません。変数でパターンを渡すことができます - バリアント 2 を参照してください。ただし、サブパターン参照 $1 を含む置換値は渡せません。バリアント 3 では、何らかの理由で置換値の $1 がサブパターン マーカーとして認識されず、リテラル '$' として扱われます。

#!/usr/bin/perl

$debug = TRUE;
$tgtfilename = $ARGV[0] || die("usage: ReplaceURLs.pl <filename> <url-pattern> <url-substvalue>");
$urlpattern  = $ARGV[1] || "href=\"\.\./\.\./(.*)\.docx\"";  # href="../../(filename).docx';
$urlsubstval = $ARGV[2] || "href=\"\$1.htm\"";  # href="$1.htm" --> href="(filename).htm";

print "replacing all occurences of pattern '$urlpattern' in file '$tgtfilename' with '$urlsubstval':\n";

# open & read $tgtfilename
open($ifh, '<', $tgtfilename) || die "unable to open $tgtfilename for reading: $!";
@slurp = <$ifh>; 
$oldstring = "@slurp";
close($ifh)  || die "can't close file $tgtfilename: $!";
if ($debug) { print $oldstring,"\n"; }

# look for $urlpattern and replace it with $urlsubstval:

# variant 1: works
#($newstring = $oldstring) =~ s!href=\"\.\./\.\./(.*)\.docx\"!href=\"$1.htm\"!g;

# variant 2: works
#($newstring = $oldstring) =~ s!$urlpattern!href=\"$1.htm\"!g; 

# variant : does not work - why?
($newstring = $oldstring) =~ s/$urlpattern/$urlsubstval/g; 

# save file
#open($ofh, '>', $tgtfilename) || die "unable to re-open $tgtfilename for writing";
#print $ofh $newstring,"\n";
#close($ofh) || die "can't close file $tgtfilename: $!";

# done
if ($debug) { print "result of replacement:","\n", $newstring,"\n"; } else { print "done."; }
__END__

「perl ReplaceURLs.pl test.htm」を使用してこれを実行すると、常に次のようになります。

<html>
 <body>
 <a href="$1.htm" />
 <a href="$1.htm" />
 <a href="$1.htm" />
 <a href="$1.htm" />
 </body>
 </html>

望ましい結果の代わりに。これを機能させるには、$urlsubstval の '$1' をどのように引用またはエスケープする必要がありますか?

M.

4

2 に答える 2

2

を参照してくださいperlop

Options are as with m// with the addition of the following replacement specific options:

     e   Evaluate the right side as an expression.
     ee  Evaluate the right side as a string then eval the result.
     r   Return substitution and leave the original string untouched.

ですから、かなりあいまいに、

$ ls -1 | perl -pE '$str = q{"--$1--"}; s/(hah)/$str/ee;'
于 2012-11-13T10:05:01.510 に答える
0

bobbogo による解決策は、$str に Perl の構文に干渉するものが含まれていない場合にのみ機能します。しかし、たまたま Perl の割り当てのように見えるもの、つまり 'href="$1.htm"' を置換に含めたかったので、これにより警告が生成されました。同様に、「置換反復子での初期化されていない値の使用...」というエラーが発生し、クラッシュしました。

したがって、私の最終的な解決策は、代わりに適切な文字列置換を使用してコマンドを作成し、次に作成したコマンドを eval(...) にすることでした。

#!/usr/bin/perl

$debug = 1;
$tgtfilename = $ARGV[0] || die("usage: ReplaceURLs.pl <filename> [ <url-pattern> [ <url-substvalue> ] ]");
$urlpattern  = $ARGV[1] || 'href="\.\./\.\./(.*)\.docx"';  # href="../../<filename>.docx"" in regexp format
$urlreplace  = $ARGV[2] || 'href="$1.htm"';  # href="$1.htm" --> href="<filename>.htm"; 

print "replacing all occurences of pattern '$urlpattern' in file '$tgtfilename' with '$urlreplace':\n";

# open & read $tgtfilename
open($ifh, '<', $tgtfilename) || die "unable to open $tgtfilename for reading: $!";
@slurp = <$ifh>; 
$oldstring = "@slurp";
close($ifh)  || die "can't close file $tgtfilename: $!";
if ($debug) { print $oldstring,"\n"; }

# construct command to look for $urlpattern and replace it with $urlreplace:
$newstring = $oldstring;
$cmd = '$newstring =~ s!'.$urlpattern.'!'.$urlreplace.'!g';
# execute it:
if ($debug) { print "cmd=", $cmd, "\n"; }
eval($cmd);

# done
if ($debug) { 
    print "result of replacement:","\n", $newstring,"\n"; 
} else { 
    # save to file:
    open($ofh, '>', $tgtfilename) || die "unable to re-open $tgtfilename for writing";
    print $ofh $newstring,"\n";
    close($ofh) || die "can't close file $tgtfilename: $!";
    print "done."; 
}
__END__
于 2012-11-13T23:47:23.067 に答える