[正規置換] 半角大かっこ閉じる "]"のエスNo.07084
rosegardenyk さん 12/07/02 15:10
 
rosegardenykです。 またマクロ初心者の質問です。v8.20 β25

質問@ 下記テスト用マクロで
半角大かっこ閉じる "]"をエスケープするすると dllfuncstr("ReplaceRegular" の
置換に失敗します($text2がブランク)。しないと置換に成功します。これは仕様で
しょうか?(一方、半角小かっこ閉じる ")" はエスケープしないと失敗します。一
貫性がないような気がするのですが) 

質問A
下記 「Bristol-Myers\Snquibb 社」の"\"をエスケープことは難しい様ですが、何か
方法がありますでしょうか? (まず無いケースなので、できなくても、気にはして
いませんがとりあえず訊きました)


//テスト用マクロ
 $text0 = "∫動脈瘤 11,660 個・年の追跡調査期間中に破裂は 111 例で確認され,
年間破裂率は 0.95%(95%信頼区間 [CI] 0.79〜1.15)であった.\n∬During a foll
ow-up period that included 11,660 aneurysm-years, ruptures were documented i
n 111 patients, with an annual rate of rupture of 0.95% (95% confidence inte
rval [CI], 0.79 to 1.15). \n∫予備的データから,腫瘍細胞の PD-L1 発現と客観
的奏効との関連が示唆される.\n∬(Funded by Bristol\Myers\Squibb and others;
ClinicalTrials.gov number, NCT00730639.) \n∫(Bristol-Myers\Snquibb 社ほか
から研究助成を受けた.\n∫ClinicalTrials.gov 番号:NCT00730639)\n\n";
 loaddll "hmjre.dll";
 #n = dllfunc("SetUnicodeIndexAutoConvert", 1);//unicode文字によるずれを解消
 $text1 = dllfuncstr("ReplaceRegular", "^(∫.+?)\n(∬.+?\n)∫(.+?\n)", $text
0, 0, "\\1\\3\\2", 2);
 while (1) {
  $$str = dllfuncstr("ReplaceRegular","(∬.+?\n)(∬.+?\n)(∫.+?\n)", $text1,
 0, "\\1\\3\\2", 0);
  if ($$str == "") break;
  $text1 = $$str;
 }
 $text1 = dllfuncstr("ReplaceRegular", "(∫.+?)\n(∬.+?\n)∫(.+?\n)\n", $tex
t1, 0, "\\1\\3\\2\n", 0);

 $text2 = $text0;  
 question "「はい」:半角大かっこ閉じる \"]\"をエスケープしない。 「いい
え」:エスケープする";
 if (result) $text0 = dllfuncstr("ReplaceRegular", "([()*+\\[\\.])", $text0,
 0, "[\\1]", 2);
 else $text0 = dllfuncstr("ReplaceRegular", "([()*+\\[\\]\\.])", $text0, 0,
"[\\1]", 2);

 $text2 = dllfuncstr("ReplaceRegular", $text0, $text2, 0, $text1, 0);
 newfile;
 insert "$text0 = \n" + $text0 + "\n$text1 = \n" + $text1  + "$text2 = \n" +
 $text2;
 endmacro;

[ ]
RE:07084 [正規置換] 半角大かっこ閉じる No.07085
秀まるお2 さん 12/07/02 17:15
 
 マクロがうまく動かない理由としてですが、まずは、

$text0 = dllfuncstr("ReplaceRegular", "([()*+\\[\\]\\.])", $text0, 0, "[\\1]
", 2);

 としてる部分は、

$text0 = dllfuncstr("ReplaceRegular", "([()*+\\[\\]\\.])", $text1, 0, "[\\\\
\\1]", 2);

 としないダメです。つまり、

    ]

 の文字は、正規表現でその文字そのものにヒットするように変換するには

    [\]]

 のように置換してやる必要があります。

 それか、そもそも

$text0 = dllfuncstr("ReplaceRegular", "([()*+\\[\\]\\.])", $text1, 0, "\\\1",
 2);

 でもいいんじゃないかという気もします。

 ただ、そう直したとしてもマクロがうまく動かないようで、その辺、そもそも
マクロが何をどうしようとしてるのか、非常に複雑で理解するのが難しいです。

 そもそも、入力されてるデータがどういう法則になっるのか、それを最終的に
どういう風に書き換えたいのかもちょっと分からないです。

 元のデータは、つまり、

∫日本語1
∬英語1
∫日本語2
∬英語2


って感じのルールの文字列なのかと思いつつも、そうでもないみたいだし…。

 ちょっとそれ以上は僕の頭で理解するのにあと1時間くらいかかりそうで、ち
ょっとパンクして、今とりあえず返事を書いてしまった所です。

[ ]
RE:07084 [正規置換] 半角大かっこ閉じる No.07086
アルビレオ さん 12/07/02 17:16
 
ユーザーのアルビレオです。

>質問@ 下記テスト用マクロで
>半角大かっこ閉じる "]"をエスケープするすると dllfuncstr("ReplaceRegular" の
>置換に失敗します($text2がブランク)。しないと置換に成功します。これは仕様で
>しょうか?(一方、半角小かっこ閉じる ")" はエスケープしないと失敗します。一
>貫性がないような気がするのですが) 

これは秀丸エディタに限らず、たいていの正規表現でそうなっていると思います。
なぜなら()の中に書かれるのは正規表現ですが、[]の中は正規表現とはまったく
別ルールの世界で、^-\] 以外の文字(.*?+など)は特別の意味を持ちません。
逆にいえば [] の外は正規表現の世界なので、単独の ] を特別なキャラクタ扱
いをする必要がないわけです。

>質問A
>下記 「Bristol-Myers\Snquibb 社」の"\"をエスケープことは難しい様ですが、何か
>方法がありますでしょうか? (まず無いケースなので、できなくても、気にはして
>いませんがとりあえず訊きました)

このテスト用マクロの場合\ によるエスケープは
 マクロ文に書かれたテキストをマクロ実行時に解釈するとき
 マクロから渡された文字変数をReplaceRegularが実行時に解釈するとき
の二段階で行われます。
だから $a = "\\\\"; と書いておけば、
 文を解釈して$aに代入される内容 → "\\"
 $aを受け取って正規表現として解釈される内容 → エスケープ文字でない単体の"\"
となります

[ ]
RE:07085 [正規置換] 半角大かっこ閉じる No.07087
rosegardenyk さん 12/07/03 00:23
 
秀まるお様
作成中の複雑なマクロを使ったため不要に混乱をもたらしてしまいました。すみませ
んでした。聞きたいのは下記マクロを実行すればわかる通り単純なことです。
下記マクロのように、何故半角大かっこ"]"はエスケープしてもしなくてもいいので
すか?
エスケープのかわりに大かっこで挟む方法は、手間のかからない実践的な方法ですが、
"[]]"で検索すると置換されないのは仕様ですか。一方で小かっこ「閉じる」は"[)]"
で置換ないし"\\\\)"でエスケープしておかないと文全体が置換されませんがこちら
が正しい仕様のような気がしました。何か理由があるのでしょうか? 


//テスト用マクロ
//大かっこの場合
 $text0 = "(95% confidence interval [CI], 0.79 to 1.15)";//元の文
 loaddll "hmjre.dll";

//ここで "confidence interval [CI]"の部分が正しくは "accurate interval [AI]
" と分かったので入れ替えたい。
 $text1 = "confidence interval [CI]"; //入れ替えたい部分
 $text2 = "accurate interval [AI]"; //正しい文言
 
 $text3 = dllfuncstr("ReplaceRegular", $text1, $text0, 0, $text2, 0);
 message "$text1 = " + $text1 + "         に  「[」 や 「]」 があるので置
換に失敗しました。 \n$text3 = " + $text3 + "*中身なし*";
 
 message "今度は $text1 の 「[」だけ をエスケープします。";
 $s = dllfuncstr("ReplaceRegular", "\\[", $text1, 0, "\\\\[", 0);
 if ($s == "") {message "$text1 の 「[」 のエスケープに失敗しました。"; endm
acro;}
 $text1 = $s;
 message "$text1 = " + $text1 + "\nこれで置換します。";
 $text3 = dllfuncstr("ReplaceRegular", $text1, $text0, 0, $text2, 0);
 message "成功です!  \n$text3 = " + $text3 + "\nでも 「]」はまだエスケー
プしてないですよね。\n 「]」 もエスケープしてみます。";
 
 $s = dllfuncstr("ReplaceRegular", "\\]", $text1, 0, "\\\\]", 0);
 if ($s == "") {message "$text1 の 「]」 のエスケープに失敗しました。"; endm
acro;}
 $text1 = $s;
 message "$text1 = " + $text1 + "\nこれで置換します。";
 $text3 = dllfuncstr("ReplaceRegular", $text1, $text0, 0, $text2, 0);
 question "これも成功です!  \n$text3 = " + $text3 + "\n「]」はまだエスケー
プしてもしなくても結果はおなじですね。
  \n正しいエスケープの方法は\\\\\\\\をたくさんつけなくてはいけなくて分かりず
らいですね。
   \n今度はエスケープではなく 大かっこ「[XXX]」で文字を囲む方法を取ってみま
しょう。 \n「いいえ」で終了します。";
 if (!result) endmacro;
 $text1 = "confidence interval [CI]";
 $text2 = "accurate interval [AI]"; //正しい文言
 message "今度は $text1 = " + $text1 + "         の 「[」だけ を「 [[] 」
に置換します。";
 $text1 = dllfuncstr("ReplaceRegular", "([\\[])", $text1, 0, "[\\1]", 2);
 message "$text1 = " + $text1 + "\nこれで置換します。";
 $text3 = dllfuncstr("ReplaceRegular", $text1, $text0, 0, $text2, 0);
 message "成功です!  \n$text3 = " + $text3 + "\nでも 「]」はまだ「[]]」に
置換してないですよね。\n 「]」 も置換してみます。";
 $text1 = "confidence interval [CI]"; //入れ替えたい部分
 $text1 = dllfuncstr("ReplaceRegular", "([\\[\\]])", $text1, 0, "[\\1]", 2);
 message "$text1 = " + $text1 + "\nこれで置換します。";
 $text3 = dllfuncstr("ReplaceRegular", $text1, $text0, 0, $text2, 0);
 question "これは失敗です。  \n$text3 = " + $text3 + "\n「]」は置換してはい
けないのですね。なぜだろう?  \n「いいえ」で終了です。";
 if (!result) endmacro;

 message "小かっこの場合はどうでしょうか?試してみましょう。";
//小かっこの場合
 $text0 = "(95% confidence interval (CI), 0.79 to 1.15)";//元の文
 loaddll "hmjre.dll";

//ここで "confidence interval [CI]"の部分が正しくは "accurate interval [AI]
" と分かったので入れ替えたい。
 $text1 = "confidence interval (CI)"; //入れ替えたい部分
 $text2 = "accurate interval (AI)"; //正しい文言
 
 $text3 = dllfuncstr("ReplaceRegular", $text1, $text0, 0, $text2, 0);
 message "$text1 = " + $text1 + "         に  「(」 や 「)」 があるので置
換に失敗しました。 \n$text3 = " + $text3 + "*中身なし*";
 
 message "今度は $text1 の 「(」だけ をエスケープします。";
 $s = dllfuncstr("ReplaceRegular", "\\(", $text1, 0, "\\\\(", 0);
 if ($s == "") {message "$text1 の 「(」 のエスケープに失敗しました。"; endm
acro;}
 $text1 = $s;
 message "$text1 = " + $text1 + "\nこれで置換します。";
 $text3 = dllfuncstr("ReplaceRegular", $text1, $text0, 0, $text2, 0);
 message "失敗です。  \n$text3 = " + $text3 + "\n「)」をまだエスケープして
ないためかもしれませんね。\n 「)」 もエスケープします。";
 
 $s = dllfuncstr("ReplaceRegular", "\\)", $text1, 0, "\\\\)", 0);
 if ($s == "") {message "$text1 の 「)」 のエスケープに失敗しました。"; endm
acro;}
 $text1 = $s;
 message "$text1 = " + $text1 + "\nこれで置換します。";
 $text3 = dllfuncstr("ReplaceRegular", $text1, $text0, 0, $text2, 0);
 message "今度は成功です! \n$text3 = " + $text3+"\n小かっこの場合は両方エス
ケープしないといけないんですね。なんかちぐはぐですね。";
 $text0 = "(95% confidence interval [CI], 0.79 to 1.15)";//元の文
 $text2 = "(95% accurate interval [AI], 0.79 to 1.15)"; //正しい文
 $text1 = $text0;//$text0全体を入れ替えるのでコピーしておきます。
 $text1 = dllfuncstr("ReplaceRegular", "([()\\[])", $text1, 0, "[\\1]", 2);
 message "最後には 小かっこも大かっこもある場合で見てみましょう \n元の文 $
text0 = " + $text0 + "\n正しい文 $text2 = " + $text2 +
 "\n置換後の検索文 $text1 = " + $text1;
 $text3 = dllfuncstr("ReplaceRegular", $text1, $text0, 0, $text2, 2);
 message "成功です!  \n$text3 = " + $text3 + "\n「]」は放置したので一発で
置換できました。こういう仕様なんでしょうか? 大かっこ[XXX]で挟むのは邪道とい
うことでしょうか?";
endmacro;

[ ]
RE:07087 [正規置換] 半角大かっこ閉じる No.07088
秀まるお2 さん 12/07/03 00:33
 
 正規表現パターンで、"[]]"と指定すれば、それは、"[]"と"]"を指定したって
意味に解釈されます。

 "[]"の部分は、何にもヒットしないので、結果として[]]も何にもヒットしな
いです。

 たとえば"[ab]"は、aまたはbという文字にのみヒットします。"[a]"ならaにの
みヒットします。[]は、中身が空っぽなのでヒットする対象の文字が無くて、結
果として何にもヒットしないです。



 "]"という文字そのものにヒットさせる正規表現パターンとしては、

     \]

 か、または、しいて[]で囲むやり方で指定するなら、

     [\]]

 になります。

[ ]
RE:07086 [正規置換] 半角大かっこ閉じる No.07089
rosegardenyk さん 12/07/03 00:49
 
アルビレオさんお返事ありがとうございます。
質問A
>このテスト用マクロの場合\ によるエスケープは
> マクロ文に書かれたテキストをマクロ実行時に解釈するとき
> マクロから渡された文字変数をReplaceRegularが実行時に解釈するとき
>の二段階で行われます。
>だから $a = "\\\\"; と書いておけば、
> 文を解釈して$aに代入される内容 → "\\"
> $aを受け取って正規表現として解釈される内容 → エスケープ文字でない単体の"\"
>となります
おっしゃる通りです。質問の仕方がまずかったです。
文字変数内で"Bristol\Myers\Squibb\n"→"Bristol\Myers\\Squibb\n"とする方法が
わからないのです。ファイルに落とした文字列ならば正規表現使わなければよいので
簡単です。以下の文字変数内置換は全て失敗です。よい手があればご教示ください。

$text0 = "Bristol\Myers\Squibb\n";
message "  $text0 = " + $text0;
 loaddll "hmjre.dll";
 $text1 = dllfuncstr("ReplaceRegular", "[B]", $text0, 0, "\\\\", 0);
message "M $text0 = " + $text1;
 $text1 = dllfuncstr("ReplaceRegular", "[\]", $text0, 0, "\\\\", 0);
message "[\] $text1 = " + $text1;
 $text1 = dllfuncstr("ReplaceRegular", "[\\]", $text0, 0, "\\\\", 0);
message "[\\] $text1 = " + $text1;
 $text1 = dllfuncstr("ReplaceRegular", "[\\\\]", $text0, 0, "\\\\", 0);
message "[\\\\] $text1 = " + $text1;
// $text1 = dllfuncstr("ReplaceRegular", "\", $text0, 0, "\\\\", 0);
//message "\ $text1 = " + $text1;
 $text1 = dllfuncstr("ReplaceRegular", "\\", $text0, 0, "\\\\", 0);
message "\\ $text1 = " + $text1;
 $text1 = dllfuncstr("ReplaceRegular", "\\\\", $text0, 0, "\\\\", 0);
message "\\\\ $text1 = " + $text1;
endmacro;

[ ]
RE:07089 [正規置換] 半角大かっこ閉じる No.07090
Iranoan さん 12/07/03 01:07
 
 rosegardenyk さん今日は、Iranoan です。
> $text0 = "Bristol\Myers\Squibb\n";
 秀丸の正規表現で「\M」はない事と、マクロであることを考えると、
$text0 = "Bristol\\Myers\\Squibb\n";
の間違いでは?

[ ]
RE:07088 [正規置換] 半角大かっこ閉じる No.07091
rosegardenyk さん 12/07/03 01:37
 
秀まるおさん、早速のお返事ありがとうございます。
>しいて[]で囲むやり方で指定するなら、  [\]]
> になります。
上記を参考に実用的な「置換用検索文」作成マクロが下記の通り出来上がりました。
 まことにありがとうございました。

まっ、半角大かっこ「閉じる」はどのやり方でも気にしなく(置換してもしなくても、
エスケープしてもしなくても)いいということですね。


 $text0 = "(95% confidence interval [CI], 0.79 to 1.15)";//元の文
 $text2 = "(95% accurate interval [AI], 0.79 to 1.15)"; //正しい文
 $text1 = $text0;//$text0全体を入れ替えるのでコピーしておきます。
 $text1 = dllfuncstr("ReplaceRegular", "([()\\[\\]])", $text1, 0, "[\\\\\\1]
", 2);//検索用置換
 message "小かっこも大かっこもある場合で見てみましょう \n元の文 $text0 = "
 + $text0 + "\n正しい文 $text2 = " + $text2 ;
 $text3 = dllfuncstr("ReplaceRegular", $text1, $text0, 0, $text2, 2);
 message "成功です!  \n$text3 = " + $text3 + "\n「]」も含めて一発で置換で
きました。\n置換後の検索文 $text1 = " + $text1;
endmacro;

[ ]
RE:07087 [正規置換] 半角大かっこ閉じる No.07092
colder さん 12/07/03 01:38
 
colderです
>//テスト用マクロ
>//大かっこの場合
> $text0 = "(95% confidence interval [CI], 0.79 to 1.15)";//元の文
> loaddll "hmjre.dll";
>
>//ここで "confidence interval [CI]"の部分が正しくは "accurate interval [A
>I]" と分かったので入れ替えたい。
> $text1 = "confidence interval [CI]"; //入れ替えたい部分
> $text2 = "accurate interval [AI]"; //正しい文言

こういうことをしたいのでしょうか?
 loaddll "hmjre.dll";
 $text1 = dllfuncstr("ReplaceRegular","([\\\\()\\[\\]{}|+*?^$.])",$text1,0,"
\\\\\\1",2);
 $text2 = dllfuncstr("ReplaceRegular","\\\\",$text2,0,"\\\\\\\\",2);
 $text0 = dllfuncstr("ReplaceRegular",$text1,$text0,0,$text2,2);

[ ]
RE:07090 [正規置換] 半角大かっこ閉じる No.07093
rosegardenyk さん 12/07/03 01:43
 
> rosegardenyk さん今日は、Iranoan です。
≪全文引用されていたのでコミュニテックス会議室システムが引用部分を省略処理し
ました。≫
>の間違いでは?
はい、$text0 = "Bristol\Myers\Squibb\n";を文字変数内で$text0 = "Bristol\\Mye
rs\\Squibb\n";に変えるマクロはどう書けばよいのかなという質問です。よろしくご
教示ください。

[ ]
RE:07089 [正規置換] 半角大かっこ閉じる No.07094
アルビレオ さん 12/07/03 01:46
 
アルビレオです。

>文字変数内で"Bristol\Myers\Squibb\n"→"Bristol\Myers\\Squibb\n"とする方法が
>わからないのです。ファイルに落とした文字列ならば正規表現使わなければよいので
>簡単です。以下の文字変数内置換は全て失敗です。よい手があればご教示ください。

>$text0 = "Bristol\Myers\Squibb\n";

この時点で無理があります。
これはすでに「改行文字を\nに置き換える」という処理を行ったあとの形式です。
今回の例ではたまたま\の後ろの文字は M と S ですが、もしも元の文字列に \
のあとに n が来る並びがあれば、改行文字を置き換えた \n と区別することは
不可能です。(他にも \ のあとにあると特殊文字として解釈されるものは txu
などたくさんあります)
そのため正規表現のことは無視しても、「秀丸マクロのリテラル文字列」として
のエスケープ処理を済ませた形式として、

$text0 = "Bristol\\Myers\\Squibb\n";

と書かないといけません。
マクロ文中に埋め込む文字列であるという時点で、これは避けようがないです。

ソース文字列の \ をそのまま単体の \ として扱いたいのならマクロ文中に埋め
込むのではなく、マクロ実行時に検索対象テキストをファイルから読み込むよう
な作戦を取る必要があります。

[ ]
RE:07092 [正規置換] 半角大かっこ閉じる No.07095
rosegardenyk さん 12/07/03 02:09
 
colderさん、お久しぶりです。またお世話になります。
>こういうことをしたいのでしょうか?
> loaddll "hmjre.dll";
> $text1 = dllfuncstr("ReplaceRegular","([\\\\()\\[\\]{}|+*?^$.])",$text1,0,
>"\\\\\\1",2);
> $text2 = dllfuncstr("ReplaceRegular","\\\\",$text2,0,"\\\\\\\\",2);
> $text0 = dllfuncstr("ReplaceRegular",$text1,$text0,0,$text2,2);
はい、こういうことをしたかったのです。まことに美しい エスケープ方式の code
ありがとうございます。

$text2 = dllfuncstr("ReplaceRegular","\\\\",$text2,0,"\\\\\\\\",2);
は $text2 = "accurate interval \\[AI]"; のように文言に\\ が入っている場合の
備えですね? はずしていたら意図をご教示ください。
  
行き違いましたが、私も [] 挟み込み方式の code 案http://www.maruo.co.jp/hidesoft/4/x07084_.html?a=4#7091
 を書いております。

[ ]
RE:07093 [正規置換] 半角大かっこ閉じる No.07096
Iranoan さん 12/07/03 02:13
 
 rosegardenyk さん今日は、Iranoan です。
> はい、$text0 = "Bristol\Myers\Squibb\n";を文字変数内で$text0 = "Bristol\\Mye
> rs\\Squibb\n";に変えるマクロはどう書けばよいのかなという質問です。よろしくご
> 教示ください。
 そういうことでなく、マクロでも「\」はエスケープ・シーケンスで、「\S」
空白以外を表すので、
$text0 = "Bristol\Myers\Squibb\n"

$text0 = "BristolMyers[^ \t\r\n]quibb\n"
と同じです。「\」自身を表したいなら、
$text0 = "Bristol\\Myers\\Squibb\n"
とする必要があります。
 やりたい事は次のマクロ?
//------------------------------------------------------------
loaddll "HmJre.dll";
$s = "Bristol\\Myers\\Squibb\n";
message $s;
$s = dllfuncstr("ReplaceRegular", "\\\\", $s, 0, "\\\\\\\\", 2 );
message $s;
freedll;

[ ]
RE:07094 [正規置換] 半角大かっこ閉じる No.07097
rosegardenyk さん 12/07/03 02:24
 
>この時点で無理があります。
丁寧な説明ありがとうございます。無理だろうなと思いながら聞いてしまいました。
了解です。主に海外医学文献を念頭に置いていますが、¥(リバース・スラッシュ
\)がひとつの文書というのもまずないとは思っております。お手数掛けてしまいま
した。またよろしくご教示ください。

[ ]
RE:07096 [正規置換] 半角大かっこ閉じる No.07098
rosegardenyk さん 12/07/03 02:49
 
>そういうことでなく、マクロでも「\」はエスケープ・シーケンスで、「\S」空白以
>外を表すので、$text0 = "Bristol\Myers\Squibb\n"は$text0 = "BristolMyers[^ \
>t\r\n]quibb\n"と同じです。「\」自身を表したいなら、$text0 = "Bristol\\Myers
>\\Squibb\n"とする必要があります。

http://www.maruo.co.jp/hidesoft/4/x07084_.html?a=7#7097に書きましたように、
無理なことというかありえないことを聞いてしまったのです。ごめんなさい。ご指摘
のように\が一つだと次の文字によって特別な意味を持ってしまうことに後から気が
付きました。Bristol Myers Squibb は製薬会社の名前なので、ちょいと空白のとこ
ろに \ を入れて例を作ってみただけでした。 お騒がせをしてしまいました。すみ
ません。 またよろしくいろいろご指導ください。 

[ ]