iT邦幫忙

3

php的preg_match 的問題

php的preg_match 的問題

想要請問:如果使用preg_match,能不能抓到指定的字之後,再讀取前面的字串及字數

例如:
$string = 臺北市信義區市府路1號;
if (preg_match("/路/i", $string)) {
echo "有路";
} else {
echo "沒有路";
}

已抓到字串裡的路,但我想要再抓市府這兩個字,需要再怎麼寫?? 能否請幫我解答~~ 謝謝

2
海綿寶寶
iT邦大神 1 級 ‧ 2020-08-18 12:31:28
最佳解答

preg_match 不是這麼用的
preg_match 是讓你用來「檢查資料是否符合自定格式」
例如:IP (nnn.nnn.nnn.nnn) 或 email address (xx.xx@xxx.xxx.xxx.xx)

preg_match 比較簡單的用法如下
1.PHP 的 preg_match 會回傳符合 Regular Expression「全部」的資料而非「部份」資料
2.拿到符合的資料後,再從裡面自己「切」出所要的資料

底下是 Step 1 的範例供參考
看看能不能用

<?php
	
echo isValid("高雄市三多路1號");
echo isValid("臺北市信義區市府路1號");
echo isValid("臺北市信義區忠孝東路1號");

function isValid($str) {
	if (preg_match("/.{6}市.{6}區.{6}路.+號/m", $str, $arr)) {
		echo $arr[0] . " is valid.\n";		
	} else {
		echo $str . " is not valid.\n";
	}
}

?>

還有
先到RegEx101去學習 Regular Expression

看更多先前的回應...收起先前的回應...

其實 preg_match 可以取得部分資料
不過要搭配正則中的集合 例如

  $string = '臺北市信義區市府路1號';
  if (preg_match('/(.*)市(.*)區(.*)路/i', $string, $matches)) {
    print_r($matches[3]); // 市府
    // echo "有路";
  } else {
    echo "沒有路";
  }

doc

其實 preg_match 可以取得部分資料

這是高手的進階用法
對初學者來說是兩面刄
/images/emoticon/emoticon10.gif

的確是
所以我也認同要先學好正則再來使用這個函數XD

真的,我真的非常認同,因第一次用到這個函數,昨天有找詢了相關的資料,看到了很多的天書文字,例如

/^[\w-]+(.[\w-]+)*@[\w-]+(.[\w-]+)+$/

很佩服前輩們怎麼能用得如行雲流水一樣, 也很謝謝大家肯耐心的回答我! 海綿寶寶listennn08浩瀚星空淺水員japhenchen 非常的謝謝您們!

可以先了解正則表達式每個符號代表的意義
正則表達式線上產生器
也可以去海綿大提供的網站練習 這樣就會比較知道在寫什麼了

2

preg_match 這樣子用跟直接用 mb_strpos 有何差別??

這樣子用 preg_match 它可是會哭的。

你參考海綿寶寶給你的範例。
學習真正的正則方式。
了解一下各函數的實際用法。
不要惡搞用法啊。

最佳解就給海綿了。

最初的想法是,每個函數都去用看看,看哪個用起來最順就用那一個,我原本是先用了explode,但以 $string ='臺北市信義區市府路1號';
用了之後,想到它只能分析到市,

$string = "臺北市信義區市府路1號";
$arr = explode("市",$string);
foreach($arr as $v){

echo $v."";
}
echo "-------------";

我的想法是:如果又再用到區,它抓出來的會變成臺北市信義區,那是不是又要再用substr 再去尾~ 但會有人像我這樣子寫嗎? 我都有點懷疑我自己了,我不知道我這樣子的表達對不對,能明白我在講什麼嗎?!!!

其實,這些都是過程。
用explode來解也是一招。

不過認真來說,你還沒遇上真正的難判斷。
有那種沒路沒街的地址你知道嘛?還有那種沒xx號的。(真的有喔,映像好像是屏東那邊的地址,太久了我也忘了)

我也給你我的經驗好了。認真來說,海綿給的跟淺水員的用法我之前都用過。explode的跑法也跑過。

但就是沒辦法符合全部的地址。我後來的做法有兩種

1.郵政區號的資料庫:去中華郵政下載一個全台地址。看是要下載詳細版(包含區碼5碼的規則)還是簡易版。拿來做比對資料庫用。
優點準確度夠
其缺點是佔用空間。且開發也比較麻煩了點。

2.google的地理庫:
將地址喂給google的地理庫api。它會幫忙做區分跟解析。
優點簡單處理
缺點就是要錢,遇到不認識的地址還會亂跑很麻煩。

以上是我後來的經驗。給你參考。

2
淺水員
iT邦高手 3 級 ‧ 2020-08-18 13:02:11
<?php
$string ='臺北市信義區市府路1號';

if(preg_match("/([^市]+)市([^區]+)區([^路]+)路/u", $string, $mch)) {
    echo "市:{$mch[1]} ";
    echo "區:{$mch[2]} ";
    echo "路:{$mch[3]} ";
} else {
    echo "不符合";
}
3
japhenchen
iT邦大師 1 級 ‧ 2020-08-18 13:08:21

preg_match不只可以檢查,也可以用()抓取資料分組

<?php

	$addr = '高雄市鼓山區厚德一路1號';
	preg_match('/.*區(?<road>[^路]+)路/u', $addr, $mat, PREG_OFFSET_CAPTURE);
	echo "路名: {$mat["road"][0]}";

?>
	

輸出

路名: 厚德一

看更多先前的回應...收起先前的回應...

記得pattern 最後要加u不然中文檢查會出槌

改進一下,這樣可以避免沒寫區的毛病

	$addr = '高雄市厚德一路1號';
	preg_match('/.*[縣市鄉鎮區鄰里](?<road>[^路]+)路/u', $addr, $mat, PREG_OFFSET_CAPTURE);
	echo "路名: {$mat["road"][0]}";

淺水員 iT邦高手 3 級 ‧ 2020-08-18 13:20:09 檢舉

路名分析其實還滿難的,例如:大里路、市政路…
如果是給使用者輸入的,感覺用選單比較好

像上面有大大用{6}來抓固定中文字數的,遇到這種

台中市西屯區市政北七路168號
一定會只剩下"北七"路

還有台積電的網頁上的地址,也會切不好
https://www.tsmc.com/chinese/contact_us.htm#TSMC_fabs

新竹科學園區園區二路168號

我只是也想要寫看看郵遞區號,像這種的,http://zip5.5432.tw/

比較簡單的就是把你看到的地址放進GOOGLE搜尋,GOOGLE會回應正確的格式跟郵政編號........呃,郵政編號的查詢就解決了

要查郵遞區號其實不會有

新竹科學園區園區二路168號

這種地址所以可以放心
japhen 大的方式也是很簡單的作法XD

謝謝您們~~讓我又學習到!

我要發表回答

立即登入回答