2016-10-12 8 views
4

私はユニコード文字をデコードしようとしています。だから私は単に私が代わりにすべてのUnicode文字をしようとしている正規表現置換e xは置換の中では機能しません

use LWP::Simple; 
my $k = get("url"); 

my ($kv) =map{/js_call\(\\"(.+?)\\"\)/} $k; 

#now $kv data is https://someurl/call.pl?id=15967737\u0026locale=en-GB\u0026mkhun=ccce 

$kv=~s/\\u(.{4})/"\x{$1}"/eg; 

内進エスケープシーケンス\x{}を試してみました。

私の予想される出力は次のようになります。

https://someurl/call.pl?id=15967737&locale=en-GB&mkhun=ccce 

は以下 print文が期待される出力を与える言及しました。しかし、正規表現は正しく動作していないようです。

print "\x{0026}"; 

答えて

7

s/\\u(.{4})/"\x{$1}"/eに問題がバックスラッシュが\x{$1}を逃れるということですが、NULLバイトを与える、コンパイル時に評価されています

$ perl -E 'printf "%vX\n", "\x{$1}"' 
0 

我々はxs/\\u(.{4})/"\\x{$1}"/ge)の前にバックスラッシュをエスケープした場合、我々はして文字列を取得しますリテラルのエスケープシーケンスが、それでも希望のUnicode文字ではない:

use feature qw(say); 
$kv = '\u0026'; 
$kv =~ s/\\u(.{4})/"\\x{$1}"/ge; 
say $kv; 

出力は以下のようになります。

\x{0026} 

少し変更して、"\x{0026}"を生成することができます。これは、コンパイルして実行して目的の値を生成できるPerlコードです。これを行うには、eval(EXPR)が必要です。

$kv =~ s/\\u(.{4})/ my $s = eval(qq{"\\x{$1}"}); die [email protected] if [email protected]; $s /ge; 

これはHowver、はるかに優れたソリューションは、以下を使用することです

$kv =~ s/\\u(.{4})/ qq{"\\x{$1}"} /gee; 

に短縮することができます:編集用

$kv =~ s/\\u(.{4})/chr hex $1/ge; 
+0

@ikegamiのおかげ! –

2

あなたがuse warningsを有効にした場合、あなたは後方参照が補間される前に$1は文字通りに評価されることを確認できます。

$kv =~ s/\\u(.{4})/ sprintf("\"\\x{%s}\"", $1) /eeg; 

種類の作品ですが、醜い醜いです。私はそれを簡素化しようとしてきましたが、私が試みた様々なアイデアは、常に「不正な16進数の「$無視された」警告に戻ってきました。

2

が、これはまた、あなたが試すことができかもしれませ:

$kv=~s/\\u([[:xdigit:]]{1,5})/chr(eval("0x$1"))/egis;

感謝。

関連する問題