次のエントリ: 置換時に式を評価する [正規表現]
前回のマッチ位置から処理する
2007-02-09-2 / カテゴリ: [perl][正規表現] / [permlink]
単に繰り返したい場合は
けど、ある正規表現にマッチした場合、その内容によって以降の処理が変化させたい、などのちょっと複雑(?)な場合は、/c /g によって、マッチ箇所を記憶させ、次に \G でその位置を参照できる。
次の正規表現でシングルクォート・ダブルクォートであれば次のクォートまで削除。コメントであれば行末まで削除。
\G の手前に . を入れてるのは、初めの正規表現でマッチした文字(' or " or #)自身。
という処理を while により繰り返す。
シェルスクリプトのコードチェックスクリプトを作成する過程で、1. コメントを削除、2. 文字列を削除 すればいーかなと思ったが、クォート内の # 以降を削ると、閉じクォートが消えてしまう。
逆にクォートを先にやると、コメント内に閉じてないクォートがある場合におかしくなってしまう。
ってことで同時にやらなきゃいけないっぽい。
複数行・ヒアドキュメント対応版
コメント・行番号無視なら
/regexp/g;/g オプションで、繰り返し処理される。
けど、ある正規表現にマッチした場合、その内容によって以降の処理が変化させたい、などのちょっと複雑(?)な場合は、/c /g によって、マッチ箇所を記憶させ、次に \G でその位置を参照できる。
# 複数行にまたがっていないコメント・文字列の削除 $r_dq = qr/(?<!\\)(?:\\\\)*\"/; while (<>) { while (/(['#]|$r_dq)/cg) { # コメントやらリテラルやらの削除 if ($1 eq "'") { # シングルクォートのリテラル削除 s/.\G.*?\'//; } elsif ($1 eq '"') { # ダブルクォートのリテラル削除 s/.\G.*?$r_dq//g; } elsif ($1 eq '#') { # コメント削除 s/.\G.*$//; } } print; }2重目の while の条件式で、まずシングルクォート、コメント、ダブルクォートを検知し、$1 の中身によって処理振り分け。
次の正規表現でシングルクォート・ダブルクォートであれば次のクォートまで削除。コメントであれば行末まで削除。
\G の手前に . を入れてるのは、初めの正規表現でマッチした文字(' or " or #)自身。
という処理を while により繰り返す。
シェルスクリプトのコードチェックスクリプトを作成する過程で、1. コメントを削除、2. 文字列を削除 すればいーかなと思ったが、クォート内の # 以降を削ると、閉じクォートが消えてしまう。
逆にクォートを先にやると、コメント内に閉じてないクォートがある場合におかしくなってしまう。
ってことで同時にやらなきゃいけないっぽい。
複数行・ヒアドキュメント対応版
$g_here = ""; $g_nest = ""; $r_dq = qr/(?<!\\)(?:\\\\)*\"/; while (<>) { if ($g_nest) { if (s/.*$g_nest//) { # 閉じられた print " $g_nest is closed (line $.)\n"; $g_nest = ""; } else { # まだ閉じてない next; } } # ヒアドキュメント中? if ($g_here) { $g_here = "" if /^$g_here$/; next; } while (/(['#]|$r_dq)/cg) { # コメントやらリテラルやらの削除 if ($1 eq "'") { # シングルクォートのリテラル削除 s/.\G.*?\'//g; } elsif ($1 eq '"') { # ダブルクォートのリテラル削除 s/.\G.*?$r_dq//g; } elsif ($1 eq '#') { # コメント削除 s/.\G.*$//g; } } # クォートの閉じ忘れチェック if (s/('|$r_dq).*//) { $g_nest = $1; print "warn? : $g_nest is not closed (line: $.)\n"; } # ヒアドキュメントチェック $g_here = $1 if /<<\s*(\w+)/; print; }全行を1変数に入れて /ms で一気にやれば楽だけど、行番号も欲しいからなぁ。
コメント・行番号無視なら
use Regexp::Common; s/$RE{quoted//g;で、クォートされてる文字列は消せる。
次のエントリ: 置換時に式を評価する [正規表現]
2013 : 01 02 03 04 05 06 07 08 09 10 11 12
2012 : 01 02 03 04 05 06 07 08 09 10 11 12
2011 : 01 02 03 04 05 06 07 08 09 10 11 12
2010 : 01 02 03 04 05 06 07 08 09 10 11 12
2009 : 01 02 03 04 05 06 07 08 09 10 11 12
2008 : 01 02 03 04 05 06 07 08 09 10 11 12
2007 : 01 02 03 04 05 06 07 08 09 10 11 12
2006 : 01 02 03 04 05 06 07 08 09 10 11 12
2005 : 01 02 03 04 05 06 07 08 09 10 11 12
2004 : 01 02 03 04 05 06 07 08 09 10 11 12
最終更新時間: 2013-05-02 16:12