次のエントリ: 置換時に式を評価する [正規表現]
前回のマッチ位置から処理する
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
