ChatGPTの回答がきっかけでpreg_replaceの仕様を調べた話
こんにちは〜!
NE株式会社のはやしまき(@_mkmk884)です🦒
みなさまコードを書く際にChatGPTやCopilotを使っていますでしょうか?
私は文字列から特定の文字列を前方一致で削除した結果を取得する処理を書く際、ChatGPTに質問しました。
preg_replaceを用いた2種類のコードがChatGPTから返ってきたので、違いを知るためにpreg_replaceの仕様を調べました!
preg_replaceを用いて前方一致にさせるコードの書き方2種類とpreg_replaceの第四引数の仕様を、このブログに残します💪
やりたいこと
文字列$completeItemCode
から特定の文字列$itemCode
を前方一致で削除し、残りの部分を抽出する処理です。
$completeItemCode = 'abc-def-ghi';
$itemCode = 'abc';
$branchNumber = '-def-ghi'; // これがほしい
ChatGPTが出してくれた前方一致で文字列置換する2種類のコード
- 正規表現を使う書き方
- 第四引数を使う書き方
の2種類をpreg_replaceを用いて回答してくれました。
正規表現を使う書き方
<?php
$data1 = ["itemCode" => "aaa", "completeItemCode" => "aaa-b-c"];
$data2 = ["itemCode" => "aaa", "completeItemCode" => "aaa-aaa-c"];
$data3 = ["itemCode" => "item", "completeItemCode" => "itembbbbc"];
function extractBranchNumber($data) {
// "itemCode" を "completeItemCode" から削除し、残りの部分を取得
$branchNumber = preg_replace('/^' . preg_quote($data["itemCode"], '/') . '/', '', $data["completeItemCode"]);
return $branchNumber;
}
// テスト
$output1 = extractBranchNumber($data1);
$output2 = extractBranchNumber($data2);
$output3 = extractBranchNumber($data3);
echo $output1 . "\n"; // 出力: -b-c
echo $output2 . "\n"; // 出力: -aaa-c
echo $output3 . "\n"; // 出力: bbbbc
?>
ChatGPTが提示してくれたもののまま記載しています。
$branchNumber = preg_replace('/^' . preg_quote($itemCode, '/') . '/', '', $completeItemCode);
正規表現のメタ文字^
を用いて、行の先頭にマッチしたもののみ置換します。
第四引数を使う書き方
<?php
function extractBranchFromCompleteItemCode($itemCode, $completeItemCode) {
// itemCodeがcompleteItemCode内で頭文字に見つかった場合
if (strpos($completeItemCode, $itemCode) === 0) {
// preg_replaceを使用して最初に見つかったitemCodeのみ削除
$branch = preg_replace("/$itemCode/", '', $completeItemCode, 1);
// 結果を返す
return $branch;
}
// インデックスが見つからない場合はエラーまたはデフォルト値を返す
return "Error: itemCode not found in completeItemCode";
}
// テストケース
$itemCode1 = "aaa";
$completeItemCode1 = "aaa-b-c";
$result1 = extractBranchFromCompleteItemCode($itemCode1, $completeItemCode1);
echo $result1 . PHP_EOL; // 出力: -b-c
$itemCode2 = "aaa";
$completeItemCode2 = "aaa-aaa-c";
$result2 = extractBranchFromCompleteItemCode($itemCode2, $completeItemCode2);
echo $result2 . PHP_EOL; // 出力: -aaa-c
$itemCode3 = "item";
$completeItemCode3 = "itembbbbc";
$result3 = extractBranchFromCompleteItemCode($itemCode3, $completeItemCode3);
echo $result3 . PHP_EOL; // 出力: bbbbc
$itemCode4 = "item";
$completeItemCode4 = "itemitemitem";
$result4 = extractBranchFromCompleteItemCode($itemCode4, $completeItemCode4);
echo $result4 . PHP_EOL; // 出力: itemitem
?>
if (strpos($completeItemCode, $itemCode) === 0) {
$branch = preg_replace("/$itemCode/", '', $completeItemCode, 1);
}
preg_replaceの第四引数って何?と思ったので、公式ドキュメントを読みました🐘
PHP: preg_replace - Manual
limit
subject 文字列において、各パターンによる 置換を行う最大回数。デフォルトは -1 (制限無し)。
とあり、このlimitに1が入っていることにより、マッチしたら最大1回置換を行うということになります。
前方一致しているかどうかの判定は、if (strpos($completeItemCode, $itemCode) === 0)
で行っており、$completeItemCode
の中で0番目(一番最初)に$itemCode
が現れているかどうかを判定しています。
PHP: strpos - Manual
(補足)実は…
実際、ChatGPTが回答してくれた第四引数を使う書き方は、以下のようにstrposで$completeItemCode
の中に$itemCode
が含まれているかどうかだけを判定しているものでした。
if (strpos($completeItemCode, $itemCode) !== false) {
$branch = preg_replace("/$itemCode/", '', $completeItemCode, 1);
}
上で書いている3、4種類のテストケースでは正しく前方一致を確認できません、、
以下のように、$completeItemCode
の文字列の途中に$itemCode
が入るパターンのテストケースが必要です。
普段はもちろんですが、生成AIに補佐してもらった際は特に意味のあるテストケースを用いてちゃんと確かめましょう😤
$itemCode5 = "item";
$completeItemCode5 = "aaaitemaaa"; // 途中に挟む
$result5 = extractBranchFromCompleteItemCode($itemCode5, $completeItemCode5);
echo $result5 . PHP_EOL;
おわりに
標準関数のデフォルト値がある引数って使う機会が少なくないですか?
今回、公式ドキュメントを読んで「そんなパラメータがあったんだ〜」となりました。
簡単な処理でも生成AIに2回聞いてみると、異なる回答をくれたりして新たな発見があるのでオススメです!
NE株式会社のエンジニアを中心に更新していくPublicationです。 NEでは、「コマースに熱狂を。」をパーパスに掲げ、ECやその周辺領域の事業に取り組んでいます。 Homepage: ne-inc.jp/
Discussion