概要

  • 入力された文字列の中の改行など直接記述できない文字にバックスラッシュを付けてエスケープする。
  • PHP関数 addcslashes / stripcslashes
  • 2つ目の引数にハッシュを指定することで別の変換を行うことができます。
    • 書いたはいいが、2番目のパラメータをハッシュだと思い込んでたがホントは文字列だった。(--;)
      addcslashes, stripcslashes という関数名は付けられないなぁ。
  • \xXX 形式には対応していません。

ソースコード

EscapeSlash.pm

# C言語スタイルで文字列のエスケープ/アンエスケープを行う
# by TakeAsh
# ネタ元 http://jp2.php.net/manual/ja/function.addcslashes.php
# ネタ元 http://blog.livedoor.jp/dankogai/archives/50940023.html
#
# v0.00	2009.03.04
# v0.01	2009.03.12	空文字列が渡されたときはundefではなく空文字列を返すようにした。
#					unescapeslashはescapeslashを呼ぶようにした。
#					\e(0x1b)もエスケープするようにした。
# v0.02	2009.03.17	数値0が渡されたときに""ではなく0を返すようにした。
# v0.03	2009.08.14	",'もエスケープするようにした。
#
# 書いたはいいが、2番目のパラメータをハッシュだと思い込んでたがホントは文字列だった。(--;)
# addcslashes, stripcslashes という関数名は付けられないなぁ。
# \xXX 形式には対応していません。

package EscapeSlash;

use strict;
use warnings;
use utf8;

use Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(escapeslash unescapeslash);

## スケープする文字セット
my %charset_factory = ( 
	"\\"=>"\\\\", "\n"=>"\\n", "\r"=>"\\r", "\t"=>"\\t", "\0"=>"\\0", 
	"\a"=>"\\a", "\b"=>"\\b", "\f"=>"\\f", "\e" => "\\e", 
	"\""=>"\\\"", "'"=>"\\'"
	# , "\v"=>"\\v"
);

##	C言語スタイルで文字列のエスケープを行う
#	@param	$str		[in] 変換対象文字列
#	@param	%charset	[in] エスケープする文字セット(オプション)
#	@return				エスケープされた文字列
sub escapeslash{
	my $str;
	$str = shift or return $str;	# undef, "", 0 ならリターン
	my %charset = defined( $_[0] ) ? %{shift()} : %charset_factory ;	# %{shift} だとハッシュへのリファレンスが受け取れない
	my $charclass = join( '|', map{ quotemeta } keys( %charset ) );
	$str =~ s/($charclass)/$charset{$1}/msgex;
	return $str;
}

##	C言語スタイルで文字列のアンエスケープを行う
#	@param	$str		[in] 変換対象文字列
#	@param	%charset	[in] アンエスケープする文字セット(オプション)
#	@return				アンエスケープされた文字列
sub unescapeslash{
	my $str = shift;
	my %charset = defined( $_[0] ) ? %{shift()} : %charset_factory ;	# %{shift} だとハッシュへのリファレンスが受け取れない
	%charset = reverse( %charset );
	return escapeslash( $str, \%charset );
}

1;

# EOF

TestEscapeSlash.pl

# EscapeSlash.pm の動作テスト

use strict;
use warnings;
use utf8;
use Data::Dump qw(dump);

use EscapeSlash;

my @Sample = (
	"ab\\cd", "ab\ncd", "ab\rcd", "ab\tcd", "ab\0cd", "ab\"cd", "ab'cd", "ab?cd", "ab&cd", 
	"ab\\\\cd", "ab\\ncd", "ab\\rcd", "ab\\tcd", "ab\\0cd", "ab\\\"cd", "ab\\'cd", "ab\\?cd", "ab\\&cd", 
	"", undef, 0, "0", 
);

my %ConvSet = ( "\\" => "\\\\", "?" => "\\?", "&"=>"\\&" );

my @TestData = ( @ARGV > 0 ) ? @ARGV : @Sample ;

print "ConvSet for esc2,unesc2\n" . dump(%ConvSet)."\n\n";

foreach my $test ( @TestData ){
	printf( "org:\t%s\n", dump($test) );
	printf( "esc:\t%s\n", dump(escapeslash($test)) );
	printf( "unesc:\t%s\n", dump(unescapeslash($test)) );
	printf( "esc2:\t%s\n", dump(escapeslash($test,\%ConvSet)) );
	printf( "unesc2:\t%s\n", dump(unescapeslash($test,\%ConvSet)) );
	#printf( "Reverse:\t%d\n", $test eq unescapeslash(escapeslash($test)) );
	print "\n";
}

# EOF

Link