[請教]取代時,判斷取代的字是完整的單字,而不是裡面的字母

edited 十月 2013 in PHP新手區
想請教各位先進,如果我現在要將$content裡面內容的某一些字,取代成我要的字,而我要取代的字已放入$ar1裡面,取代成$ar2,程式碼如下:

foreach($ar1 as $key => $value)
{
$content = str_replace($value, $ar2[$key], $content);
}



假設我要取代的字是an、ant、anti
那在$content裡面,如果有anti-spam,這樣的字母
an會取代一次、ant也會取代一次、anti也會取代一次
我想問的是說,如何才能讓他字母完全符合anti-spam時,才會進行取代
而不是裡面有字母相同就會取代,取代的字數必須完取符合才行
還是有比較好的方法嗎?
苦惱中...

win2003
appserv

原始討論: http://twpug.net/x/modules/newbb/viewtopic.php?topic_id=1238

評論

  • edited 二月 2006
    補充一下:
    簡單說,假設我要取代『a』變成『an』
    如何判斷說,我取代的字是完整的一個『單字』
    不然的話,假設apple可能就會變成anpple了

    再假設,$content = "a apple a day keeps a doctor away";
    $content = str_replace("a", "an", $content);
    echo $content;
    就會變成 "an anpple an dany keeps an doctor anwany" ....

    所以我希望取代的時候,能夠判斷他取代的是一個單字,而不是裡面的字母
    苦惱中...
  • edited 二月 2006
    lucars 寫道:
    補充一下:
    簡單說,假設我要取代『a』變成『an』
    如何判斷說,我取代的字是完整的一個『單字』
    不然的話,假設apple可能就會變成anpple了

    再假設,$content = "a apple a day keeps a doctor away";
    $content = str_replace("a", "an", $content);
    echo $content;
    就會變成 "an anpple an dany keeps an doctor anwany" ....

    所以我希望取代的時候,能夠判斷他取代的是一個單字,而不是裡面的字母
    苦惱中...

    這部分需要依照實際情況分析

    以你提出的例子,由於是英文句子
    可以考慮用"a "來處理而不是用"a"
    這樣就不會跟其他的a衝突到(單字尾如果有a的就....)

    另外你提到的an、ant、anti取代$content裡面的anti-spam
    這要看你取代哪種單字
    假設是用bn取代,那祇會被an取代一次而已
    因為第一次取代後anti-spam會變成bnti-spam
    後續的ant跟anti就不會繼續取代
  • edited 二月 2006
    我其實也考慮過這樣的問題,所以我寫了個function來判斷所有的狀況,可是狀況實在是太多了,根本無法去判斷完,而且模擬兩可的狀況也不少。
    像我當初考慮的是,一個單字,前後一定是空字元,才算是一個單字,所以我取代的時候是 str_replace(" ".$value." ", " ".$ar2[$key]." ", $content); 以空字元來區隔開來,確定他是一個單字。
    不過後來又考慮到,有類似這樣的狀況
    John say "Hello".
    像這樣,John前面不是空白字元,Hello被"與.給包起來
    如果把前面不是空白字元這情況也考慮下去,變成妳說的那種狀況,只要John的字母是包含在單字後面的,就會被取代掉...

    所以想說有其他更好的方式嗎?
  • edited 二月 2006
    lucars 寫道:
    我其實也考慮過這樣的問題,所以我寫了個function來判斷所有的狀況,可是狀況實在是太多了,根本無法去判斷完,而且模擬兩可的狀況也不少。
    像我當初考慮的是,一個單字,前後一定是空字元,才算是一個單字,所以我取代的時候是 str_replace(" ".$value." ", " ".$ar2[$key]." ", $content); 以空字元來區隔開來,確定他是一個單字。
    不過後來又考慮到,有類似這樣的狀況
    John say "Hello".
    像這樣,John前面不是空白字元,Hello被"與.給包起來
    如果把前面不是空白字元這情況也考慮下去,變成妳說的那種狀況,只要John的字母是包含在單字後面的,就會被取代掉...

    所以想說有其他更好的方式嗎?

    如果是抓單字的話....
    考慮用explode如何?
    可將字串依指定的字串或字元切開成array。
  • edited 二月 2006
    explode的功能是依照指定的字元來切割字串變成陣列
    是可以把每個單字分開沒錯,不過卻無法在取代之後將陣列還原成字串(也就是說無法百分之百還原成原編排方式),這樣取代就沒有意義了...(因為要考慮到單字比對與編排的問題,裡面會包含 ' ; " . ! ?等符號...如果是explode(" ", $content);的話,則會把這些符號包含進去,如果用replace("!", "", $content)的方式,則還原成字串會少掉 "!" 這個符號)
    不過還是很感謝大大的回覆,不曉得是否還有其他的方式可以提供思考、參考的
  • edited 二月 2006
    lucars 寫道:
    explode的功能是依照指定的字元來切割字串變成陣列
    是可以把每個單字分開沒錯,不過卻無法在取代之後將陣列還原成字串(也就是說無法百分之百還原成原編排方式),這樣取代就沒有意義了...(因為要考慮到單字比對與編排的問題,裡面會包含 ' ; " . ! ?等符號...如果是explode(" ", $content);的話,則會把這些符號包含進去,如果用replace("!", "", $content)的方式,則還原成字串會少掉 "!" 這個符號)
    不過還是很感謝大大的回覆,不曉得是否還有其他的方式可以提供思考、參考的

    這個我不怎同意!

    舉個例子
    用" "切割成array,那回組也是用" "填回去
    Tihs is a example.
    切成array會是{"This", "is", "a", "example."}
    把a取代掉成an好了,還原回去變成
    This is an example.

    我不認為有什麼還原問題存在
    而' ; " . ! ?這些符號,當然也可以一起考慮當成explode的切割字元來組成多維陣列
    處理完畢再一層一層反向還原回去,組成原本的文章並非做不到的

    一點淺見,提出來大家討論討論 ├151┤
  • edited 二月 2006
    確實如此,感謝前輩的提醒
    其實,我之前也有想過用explode來分割
    不過後來考慮到標點符號的問題,會造成比對的困難
    而且還原成原內容有些困難

    不過後來經由前輩再次提醒,發覺並非不可行,確實有他的可行性
    例如符號之類的,可以在切割完內容之後,再切割一次,然後再進行取代,取代完之後,再組合回去,一個字一個字下去檢查,確實有他的可行性在

    有時候自己的一個觀念,就會把自己給鎖死在自己的想法中
    藉由討論的方式,又可以把一些自己認定的觀念給推翻掉
    感謝大大有耐心、且不吝嗇的討論,我目前也有了一些雛形了
    正在努力的組合中! bravo ~! ├138┤
  • edited 二月 2006
    為什摩不用RegExp 的相關函數呢?
    一行搞定!
    $str='John say "Hello". ';
    $pattern="/\b\w+\b/";
    
    preg_match_all($pattern,$str,$matchs);
    
    print_r ($matchs);
    

    \b
    文字邊界
    \w
    任何英文單字的其中一個字元
    + 至少要一個

    注意,$match[1]才是第一個取出的結果, $match[0] 不是
  • edited 二月 2006
    snaking 寫道:
    為什摩不用RegExp 的相關函數呢?
    一行搞定!
    $str='John say "Hello". ';
    $pattern="/\b\w+\b/";
    
    preg_match_all($pattern,$str,$matchs);
    
    print_r ($matchs);
    

    \b
    文字邊界
    \w
    任何英文單字的其中一個字元
    + 至少要一個

    注意,$match[1]才是第一個取出的結果, $match[0] 不是

    因為我對常規表示法不是非常熟練,所以只能提出自己比較熟悉的寫法。
    常規表示法功能非常強大,自己沒深入了解,提出來反而幫不上忙 ├004┤
  • edited 二月 2006
    snaking 寫道:
    為什摩不用RegExp 的相關函數呢?
    一行搞定!
    $str='John say "Hello". ';
    $pattern="/\b\w+\b/";
    
    preg_match_all($pattern,$str,$matchs);
    
    print_r ($matchs);
    

    \b
    文字邊界
    \w
    任何英文單字的其中一個字元
    + 至少要一個

    注意,$match[1]才是第一個取出的結果, $match[0] 不是

    我也沒用過RegExp這個function
    好像滿有趣的,不過由於標點符號的位置也要考慮下去
    (像是can't的 ' 或是"hello"的 " )
    可以請教一下該怎麼表示比較好嗎?
    因為我也沒用過,想詢問依下怎麼寫會比較好

    這是我print_r()出來的結果
    Array ( [0] => Array ( [0] => John [1] => say [2] => Hello ) )
    ├142┤
  • edited 二月 2006
    其實RegExp 就像益智玩具般,挑動人們想要解謎的興趣! 我也是每次見招拆招而已!

    新的問題解法:
    $str='John\'s brother say \'Hello\'. ';
    
    $pattern="/\b[\w']+\b/";
    
    preg_match_all($pattern,$str,$matchs);
    print_r ($matchs);
    
    Array ( [0] => Array ( [0] => John's [1] => brother [2] => say [3] => Hello ) )

    你不是說 "Hello" 只取Hello嗎?
  • edited 二月 2006
    不過說起來慚愧,我竟然寫不出等同於

    explode(" ",$str);

    的regexp表示法
  • edited 二月 2006
    不,我真正的意思是指說,一篇文章要如何取代時,會取代一個完整的字,所以,當妳取代完後,必須再還原成一篇文章,當然包含標點符號在內 ^_^

    感謝大大提供的意見,讓我又學了新的東西,這樣討論就很值回票價了 ├138┤
    目前這問題已經解決了,目前是用explode來取出每個單字,包含各個標點符號,然後在進行多重取代方式,將標點符號分離之後,取代單字再還原,感謝各位前輩的討論與指教,謝謝。 ├138┤
  • edited 二月 2006
    恭喜你解決了!

    沒寫Replace的部分,是想留給你慢慢玩!
    翻一下函數手冊,preg_replace 可以這樣用,讓程式更簡潔!
    :
    Example 1. Replacing several values
    
    $patterns = array ("/(19|20)(\d{2})-(\d{1,2})-(\d{1,2})/",
                       "/^\s*{(\w+)}\s*=/");
    $replace = array ("\\3/\\4/\\1\\2", "$\\1 =");
    print preg_replace ($patterns, $replace, "{startDate} = 1999-5-27");
     
     
    This example will produce: $startDate = 5/27/1999
     
    Example 2. Using /e modifier
    
    preg_replace ("/(<\/?)(\w+)([^>]*>)/e", 
                  "'\\1'.strtoupper('\\2').'\\3'", 
                  $html_body);
     
    
    This would capitalize all HTML tags in the input text. 
     
    Example 3. Convert HTML to text
    
    // $document should contain an HTML document.
    // This will remove HTML tags, javascript sections
    // and white space. It will also convert some
    // common HTML entities to their text equivalent.
    
    $search = array ("'<script[^>]*?>.*?</script>'si",  // Strip out javascript
                     "'<[\/\!]*?[^<>]*?>'si",           // Strip out html tags
                     "'([\r\n])[\s]+'",                 // Strip out white space
                     "'&(quot|#34);'i",                 // Replace html entities
                     "'&(amp|#38);'i",
                     "'&(lt|#60);'i",
                     "'&(gt|#62);'i",
                     "'&(nbsp|#160);'i",
                     "'&(iexcl|#161);'i",
                     "'&(cent|#162);'i",
                     "'&(pound|#163);'i",
                     "'&(copy|#169);'i",
                     "'&#(\d+);'e");                    // evaluate as php
    
    $replace = array ("",
                      "",
                      "\\1",
                      "\"",
                      "&",
                      "<",
                      ">",
                      " ",
                      chr(161),
                      chr(162),
                      chr(163),
                      chr(169),
                      "chr(\\1)");
    
    $text = preg_replace ($search, $replace, $document);
    

    另外推薦一個可以自訂出更多處理方式的函數:preg_replace_callback
  • edited 二月 2006
    漂亮...感謝前輩的提供
    看樣子,可以好好解讀一陣子了... ├140┤

    先抓下來研究一下... ├128┤
Sign In or Register to comment.