str_replace — 子字符串替换 [str_replace]
mixed str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] )
php函数str_replace: 返回一个字符串或者数组。该字符串或数组是将 subject 中全部的 search 都被 replace 替换之后的结果。
现在我们所能知道的一些这个函数的用法,如:str_replace("#", "-", "dizaz#7#final"),str_replace(array('#', '$'), "-", "dizaz#7$final") 等,就这些调用方式,php内部是如何实现的呢,鉴于[深入理解PHP内核],在这里小做分析。
测试代码:
$object = "dizaz#7#final";
$res = str_replace("#", "-", $object);
echo $res;
如上,先从字符“#”替换为字符“-”开始。
预备工作:
下载PHP源代码,http://www.php.net下载即可
打造自己的阅读代码的工具[本人使用VIM+CSCOPE] 另:Linux用户也推荐图形化查看源代码工具kscope [google之]
编译工具[gcc],调试工具[gdb],另:GDB图形化端口DDD也很不错,推荐
编译PHP源码,记得使用--enable-debug [当然也希望通过./configure --help 看看PHP提供的一些编译选项,会有很多收获的]
开始分析:
通过[深入理解PHP内核]阅读,我们不难发现其PHP提供标准函数所在目录为PHP-SOURCE-DIR/ext/standard目录下,由于是字符串函数,很容易我们就可以在此目录下找到str_replace函数实现的文件 string.c,接下来就围绕着这个文件进行分析。[当然用CScope很容易就可以锁定,用:cs find s str_replace]
查询得知其定义实现:
/* {{{ proto mixed str_replace(mixed search, mixed replace, mixed subject [, int &replace_count])
Replaces all occurrences of search in haystack with replace */
PHP_FUNCTION(str_replace)
{
php_str_replace_common(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
}
/* }}} */
现在需要查看函数php_str_replace_common函数
/* {{{ php_str_replace_common
*/
static void php_str_replace_common(INTERNAL_FUNCTION_PARAMETERS, int case_sensitivity)
{
/**
* TODO
* typedef struct _zval_struct zval;
* typedef struct _zend_class_entry zend_class_entry
*
* struct _zval_struct {
* zvalue_value value;
* zend_uint refcount__gc;
* zend_uchar type;
* zend_uchar is_ref__gc;
* };
*
* typedef union _zvalue_value {
* long lval;
* double dval;
* struct {
* char *val;
* int len;
* } str;
* HashTable *ht;
* zend_object_value obj;
* } zvalue_value;
*
* typedef struct _zend_object {
* zend_class_entry *ce;
* HashTable *properties;
* HashTable *guards;
* } zend_object;
*
*/
zval **subject, **search, **replace, **subject_entry, **zcount = NULL;
zval *result;
char *string_key;
uint string_key_len;
ulong num_key;
int count = 0;
int argc = ZEND_NUM_ARGS();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZZ|Z", &search, &replace, &subject, &zcount) == FAILURE) {
return;
}
SEPARATE_ZVAL(search);
SEPARATE_ZVAL(replace);
SEPARATE_ZVAL(subject);
/* Make sure we're dealing with strings and do the replacement. */
if (Z_TYPE_PP(search) != IS_ARRAY) {
....//代码省滤
} else { /* if subject is not an array */
php_str_replace_in_subject(*search, *replace, subject, return_value, case_sensitivity, (argc > 3) ? &count : NULL);
}
if (argc > 3) {
zval_dtor(*zcount);
ZVAL_LONG(*zcount, count);
}
}
/* }}} */
继续跟踪php_str_replace_in_subject
/* {{{ php_str_replace_in_subject
*/
static void php_str_replace_in_subject(zval *search, zval *replace, zval **subject, zval *result, int case_sensitivity, int *replace_count)
{
zval **search_entry,
**replace_entry = NULL,
temp_result;
char *replace_value = NULL;
int replace_len = 0;
/* Make sure we're dealing with strings. */
convert_to_string_ex(subject);
Z_TYPE_P(result) = IS_STRING;
if (Z_STRLEN_PP(subject) == 0) {
ZVAL_STRINGL(result, "", 0, 1);
return;
}
/* If search is an array */
if (Z_TYPE_P(search) == IS_ARRAY) {
...//不走这步
} else {
if (Z_STRLEN_P(search) == 1) { //例子中只有”#“所以,执行这一步。
php_char_to_str_ex(Z_STRVAL_PP(subject),//subject的值,也就是dizaz#7#final
Z_STRLEN_PP(subject), //获取subject的长度
Z_STRVAL_P(search)[0], //由于只有1个”#”,所以只需要第一个字符
Z_STRVAL_P(replace), //所要替换成的字符,现在是“-”
Z_STRLEN_P(replace), //目标字符的长度,现在为1
result, //替换结果
case_sensitivity, //大小写是否敏感,默认是1
replace_count); //替换次数
} else if (Z_STRLEN_P(search) > 1) {
Z_STRVAL_P(result) = php_str_to_str_ex(Z_STRVAL_PP(subject), Z_STRLEN_PP(subject),
Z_STRVAL_P(search), Z_STRLEN_P(search),
Z_STRVAL_P(replace), Z_STRLEN_P(replace), &Z_STRLEN_P(result), case_sensitivity, replace_count);
} else {
MAKE_COPY_ZVAL(subject, result);
}
}
}
到现在为止,我们的目标最终锁定到了php_char_to_str_ex 函数,现在只需要分析这个函数就OK了。其实现为:
/* {{{ php_char_to_str_ex
*/
PHPAPI int php_char_to_str_ex(char *str, uint len, char from, char *to, int to_len, zval *result, int case_sensitivity, int *replace_count)
{
int char_count = 0;
int replaced = 0;
char *source, *target, *tmp, *source_end=str+len, *tmp_end = NULL;
if (case_sensitivity) { //现在case_sensitivity = 1
char *p = str, *e = p + len;
//计算需要替换几次
while ((p = memchr(p, from, (e - p)))) {
char_count++;
p++;
}
} else {
for (source = str; source if (tolower(*source) == tolower(from)) {
char_count++;
}
}
}
if (char_count == 0 && case_sensitivity) {
ZVAL_STRINGL(result, str, len, 1);
return 0;
}
//计算替换以后的长度,并且存储到result中。
Z_STRLEN_P(result) = len + (char_count * (to_len - 1));
//申请内存,存放替换后的数据
Z_STRVAL_P(result) = target = safe_emalloc(char_count, to_len, len + 1);
//设定结果是一个字符串
Z_TYPE_P(result) = IS_STRING;
//target跟result的值都指向统一块内存,所以只需要处理target
if (case_sensitivity) {
char *p = str, *e = p + len, *s = str;
while ((p = memchr(p, from, (e - p)))) { //判断在第几个字符出现#
memcpy(target, s, (p - s)); //把#以前的数据拷贝给target
target += p - s;
memcpy(target, to, to_len); //把目标字符拷贝给target[当然此时的target是开始target+p-s的]
target += to_len;
p++;
s = p;
if (replace_count) {
*replace_count += 1; //设定替换次数
}
}
//如果后面还有,继续添加到target后,这样target所指向的内存块已经是替换好的数据了。
if (s memcpy(target, s, (e - s));
target += e - s;
}
} else {
for (source = str; source if (tolower(*source) == tolower(from)) {
replaced = 1;
if (replace_count) {
*replace_count += 1;
}
for (tmp = to, tmp_end = tmp+to_len; tmp *target = *tmp;
target++;
}
} else {
*target = *source;
target++;
}
}
}
*target = 0;
return replaced;
}
/* }}} */
如上注释,其就这样完成了对于字符到字符串的替换。至于其中怎么return,怎么一个详细的过程,需要再对PHP执行过程有个相对的了解。
当然可以用gdb下断点到php_char_to_str_ex函数,来了解其详细执行过程。
下一篇来做对于字符串替换成字符串的分析。
小结:
其结果是存在zval中
其对替换的实现比较巧妙,可以学习
需要继续查看源码,学习更多编写技巧以及设计技巧。

종종 키워드와 추적 매개 변수로 혼란스러워하는 긴 URL은 방문자를 방해 할 수 있습니다. URL 단축 스크립트는 솔루션을 제공하여 소셜 미디어 및 기타 플랫폼에 이상적인 간결한 링크를 만듭니다. 이 스크립트는 개별 웹 사이트 a에 유용합니다

Instagram은 2012 년 Facebook에서 유명한 인수에 이어 타사 사용을 위해 두 개의 API 세트를 채택했습니다. Instagram Graph API 및 Instagram Basic Display API입니다. 개발자는

Laravel은 직관적 인 플래시 방법을 사용하여 임시 세션 데이터 처리를 단순화합니다. 응용 프로그램에 간단한 메시지, 경고 또는 알림을 표시하는 데 적합합니다. 데이터는 기본적으로 후속 요청에만 지속됩니다. $ 요청-

이것은 Laravel 백엔드가있는 React Application을 구축하는 데있어 시리즈의 두 번째이자 마지막 부분입니다. 이 시리즈의 첫 번째 부분에서는 기본 제품 목록 응용 프로그램을 위해 Laravel을 사용하여 편안한 API를 만들었습니다. 이 튜토리얼에서는 Dev가 될 것입니다

Laravel은 간결한 HTTP 응답 시뮬레이션 구문을 제공하여 HTTP 상호 작용 테스트를 단순화합니다. 이 접근법은 테스트 시뮬레이션을보다 직관적으로 만들면서 코드 중복성을 크게 줄입니다. 기본 구현은 다양한 응답 유형 단축키를 제공합니다. Illuminate \ support \ Facades \ http를 사용하십시오. http :: 가짜 ([ 'google.com'=> 'Hello World', 'github.com'=> [ 'foo'=> 'bar'], 'forge.laravel.com'=>

PHP 클라이언트 URL (CURL) 확장자는 개발자를위한 강력한 도구이며 원격 서버 및 REST API와의 원활한 상호 작용을 가능하게합니다. PHP CURL은 존경받는 다중 프로모토콜 파일 전송 라이브러리 인 Libcurl을 활용하여 효율적인 execu를 용이하게합니다.

고객의 가장 긴급한 문제에 실시간 인스턴트 솔루션을 제공하고 싶습니까? 라이브 채팅을 통해 고객과 실시간 대화를 나누고 문제를 즉시 해결할 수 있습니다. 그것은 당신이 당신의 관습에 더 빠른 서비스를 제공 할 수 있도록합니다.

2025 PHP Landscape Survey는 현재 PHP 개발 동향을 조사합니다. 개발자와 비즈니스에 대한 통찰력을 제공하는 프레임 워크 사용, 배포 방법 및 과제를 탐색합니다. 이 조사는 현대 PHP Versio의 성장을 예상합니다


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

DVWA
DVWA(Damn Vulnerable Web App)는 매우 취약한 PHP/MySQL 웹 애플리케이션입니다. 주요 목표는 보안 전문가가 법적 환경에서 자신의 기술과 도구를 테스트하고, 웹 개발자가 웹 응용 프로그램 보안 프로세스를 더 잘 이해할 수 있도록 돕고, 교사/학생이 교실 환경 웹 응용 프로그램에서 가르치고 배울 수 있도록 돕는 것입니다. 보안. DVWA의 목표는 다양한 난이도의 간단하고 간단한 인터페이스를 통해 가장 일반적인 웹 취약점 중 일부를 연습하는 것입니다. 이 소프트웨어는

SecList
SecLists는 최고의 보안 테스터의 동반자입니다. 보안 평가 시 자주 사용되는 다양한 유형의 목록을 한 곳에 모아 놓은 것입니다. SecLists는 보안 테스터에게 필요할 수 있는 모든 목록을 편리하게 제공하여 보안 테스트를 더욱 효율적이고 생산적으로 만드는 데 도움이 됩니다. 목록 유형에는 사용자 이름, 비밀번호, URL, 퍼징 페이로드, 민감한 데이터 패턴, 웹 셸 등이 포함됩니다. 테스터는 이 저장소를 새로운 테스트 시스템으로 간단히 가져올 수 있으며 필요한 모든 유형의 목록에 액세스할 수 있습니다.

Atom Editor Mac 버전 다운로드
가장 인기 있는 오픈 소스 편집기

ZendStudio 13.5.1 맥
강력한 PHP 통합 개발 환경
