sscanf

(PHP 4 >= 4.0.1, PHP 5, PHP 7, PHP 8)

sscanf根据格式解析字符串中的输入

描述

sscanf(string $string, string $format, mixed &...$vars): array|int|null

函数 sscanf()printf() 的输入类似物。 sscanf() 从字符串 string 中读取,并根据指定的 format 进行解释。

格式字符串中的任何空格都与输入字符串中的任何空格匹配。这意味着格式字符串中的制表符 (\t) 甚至可以与输入字符串中的单个空格字符匹配。

参数

string

要解析的输入 string

format

string 的解释格式,在 sprintf() 文档中有所描述,但存在以下差异

  • 函数不是本地化的。
  • FgGb 不受支持。
  • D 代表十进制数。
  • i 代表带有基数检测的整数。
  • n 代表迄今为止处理的字符数。
  • s 在任何空格字符处停止读取。
  • * 而不是 argnum$ 抑制此转换规范的赋值。

vars

可选地按引用传递变量,这些变量将包含解析的值。

返回值

如果仅将两个参数传递给此函数,则解析的值将作为数组返回。否则,如果传递了可选参数,则函数将返回分配的值数量。可选参数必须按引用传递。

如果 format 中期望的子字符串数量多于 string 中可用的子字符串数量,则将返回 null

示例

示例 #1 sscanf() 示例

<?php
// 获取序列号
list($serial) = sscanf("SN/2350001", "SN/%d");
// 以及制造日期
$mandate = "January 01 2000";
list(
$month, $day, $year) = sscanf($mandate, "%s %d %d");
echo
"Item $serial was manufactured on: $year-" . substr($month, 0, 3) . "-$day\n";
?>

如果传递了可选参数,则函数将返回分配的值数量。

示例 #2 sscanf() - 使用可选参数

<?php
// 获取作者信息并生成 DocBook 条目
$auth = "24\tLewis Carroll";
$n = sscanf($auth, "%d\t%s %s", $id, $first, $last);
echo
"<author id='$id'>
<firstname>
$first</firstname>
<surname>
$last</surname>
</author>\n"
;
?>

参见

添加备注

用户贡献的备注 18 个备注

68
jon at fuck dot org
21 年前
此函数是将 HTML 等效十六进制值转换为整数 RGB 值的好方法。

list($r, $g, $b) = sscanf('00ccff', '%2x%2x%2x');
17
elgabos at umail dot ucsb dot edu
22 年前
在玩了一段时间后,我发现如果你使用 %[^[]] 而不是 %s(因为 php 在使用 %s 时存在空格问题),它能很好地工作。

对于那些不熟悉正则表达式的人来说,%[^[]] 基本上匹配任何不是空的东西。

希望这有帮助。- Gabe
16
mikewillitsgmail.com
16 年前
提醒一下 - 如果你尝试从包含带扩展名的文件名的字符串中扫描。例如

<?php

$out
= sscanf('file_name.gif', 'file_%s.%s', $fpart1, $fpart2);

?>

参数 $fpart1 中的扫描字符串结果为 'name.gif',而 $fpart2 将为 NULL。

为了解决这个问题,你可以简单地将“.”替换为空格或其他“类似空格”的字符串序列。

我没有看到关于包含“.”的字符串文字的其他评论,因此我想提一下。我认为具有“空格分隔”的内容的微妙特性可能是使用冲突的来源。显然,另一种方法是在这种情况下使用正则表达式,但对于新用户来说,这可能会有所帮助。

以防其他人像我一样花费了 10 分钟的沮丧。这在 PHP 版本 5.2.3-1ubuntu6.3 上看到。

搜索错误报告显示了另一位用户的误解:http://bugs.php.net/bug.php?id=7793
4
Brainiac361
18 年前
%[^[]]-技巧可能看起来有效,但它没有!

发生的事情是 sscanf 只会匹配任何字符,但不会匹配左方括号(这相当罕见,这就是为什么它可能看起来有效的原因)。
但更糟糕的是,它会期望接下来出现一个 ]-字符,并继续匹配任何字符。

现在,你可以做的是让 sscanf 查找除一个永远不会使用的字符之外的任何字符... 一个不错的选择是换行符 "%[^\\n]",尤其是在与 fscanf 结合使用时。

你也可以复制粘贴任何未使用的 ASCII 字符,比如 #001 或类似的字符。
6
leg
16 年前
@mikewillitsgmail.com

<?php

$out
= sscanf('file_name.gif', 'file_%[^.].%s', $fpart1, $fpart2);

echo
'<pre>';
print_r($fpart1);
echo
'<hr />';
print_r($fpart2);
echo
'</pre>';

?>

输出

name
-
gif

“^.” 部分避免了第一个搜索字符串过贪婪。 但是不能防止“file_test.name.gif”之类的输入,会导致错误的结果!
3
codeslinger at compsalot dot com
19 年前
安全说明

尽管它是一种非常强大的技术,但请记住它很容易被欺骗。

许多成功的攻击都是基于 scanf 攻击。 不应该在未经验证的输入上使用它,除非进行了大量的额外验证。
3
Vincent Jansen
19 年前
如果您只是想过滤字符串中两个部分之间的信息,我使用了以下方法,对我来说比 sscanf 函数更有效。

<?php
function scanstr($zoekstr,$part1,$part2) {
$firstpos=strpos ($zoekstr, $part1)+strlen($part1);
$lastpos=strpos ($zoekstr, $part2);
$scanresult=substr ($zoekstr, $firstpos, $lastpos-$firstpos);
return(
$scanresult);
}
echo
scanstr ("var1=hello&var2=test&var3=more","var2=","&var3");
?>
2
anonymouse
18 年前
我见过很多例子,人们使用方括号来定义看起来像正则表达式字符类的结构。 在我有限的测试中,我认为它们不是真正的字符类,但它们似乎很相似。

我的任务是使用 sscanf() 解析格式为以下格式的字符串数组:

数字 空格 可能也包含空格的字符串

普通的 %s 转换命令将空格视为某种分隔符。 因此,如果您事先知道有多少个“单词”,您就可以获取字符串。 但是,我的输入是可变的。

这是我想到的:(注意使用美元符号“字符串结尾”隐藏分隔符)

sscanf($string_to_parse,'%d %[^$]s',$num,$text);

此转换命令表示“查找一个整数,然后是一个空格,然后是直到字符串结尾的任何字符串”
2
skeltoac
18 年前
解析来自 Apache 访问日志的以通用格式的一行

<?php
$log
= array();
$n = sscanf(trim($line), '%s %s %s [%[^]]] "%s %s %[^"]" %d %s "%[^"]" "%[^"]"',
$log['ip'],
$log['client'],
$log['user'],
$log['time'],
$log['method'],
$log['uri'],
$log['prot'],
$log['code'],
$log['bytes'],
$log['ref'],
$log['agent']
);
?>
2
Victor
11 年前
需要注意的是:与 C/C++ 不同,分配给变量 %n 的值将计入返回值中。
2
narainsbrain at yahoo dot com
22 年前
显然,sscanf 始终在空格处拆分,即使格式中未指定空格。 考虑以下脚本

<?php
$str
= "This is a\tsentence with\ttabs";
$scanned = sscanf($str, "%s\t%s\t%s");
echo
join(" : ", $scanned);
?>

这会回显“This : is : a”,而不是预期的“This is a : sentence with : tabs”。
如果您的字符串不包含空格,这种行为是可以的,但是如果包含空格,您最好使用 explode()。
0
Philo
4 年前
还应注意,与 sscanf 一起使用时,x 和 X 会产生相同的输出(即它们不区分大小写)。

<?php
var_dump
(sscanf("0xdead|0XDEAD", "%X|%x")); // 工作
0
joshmckenneyATgmailDOT(0{
19 年前
在电话号码函数中添加了国家代码 (1)

function formatPhone($phone) {
if (empty($phone)) return "";
if (strlen($phone) == 7)
sscanf($phone, "%3s%4s", $prefix, $exchange);
else if (strlen($phone) == 10)
sscanf($phone, "%3s%3s%4s", $area, $prefix, $exchange);
else if (strlen($phone) > 10)
if(substr($phone,0,1)=='1') {
sscanf($phone, "%1s%3s%3s%4s", $country, $area, $prefix, $exchange);
}
else{
sscanf($phone, "%3s%3s%4s%s", $area, $prefix, $exchange, $extension);
}
else
return "未知电话格式: $phone";
$out = "";
$out .= isset($country) ? $country.' ' : '';
$out .= isset($area) ? '(' . $area . ') ' : '';
$out .= $prefix . '-' . $exchange;
$out .= isset($extension) ? ' x' . $extension : '';
return $out;
}
-1
clcollie at mindspring dot com
23 年前
实际上 sscanf()_始终_ 返回一个数组,如果您指定的返回值变量少于格式说明符。 我可能会将此更改为,如果只有一个格式说明符,则返回一个标量。
请注意,sscanf() 几乎完全等效于其“C”对应项,因此您可以执行以下操作以获得预期的效果

sscanf("SN/2350001","SN/%d",&$serial)

数组返回值是 PHP 的一种便利。
-3
marcus at synchromedia dot co dot uk
21 年前
在 PHP >= 4.3.0 中,如果您使用额外的引用参数,您将收到以下警告

PHP 警告:调用时按引用传递已弃用 - 参数按值传递

这显然有可能导致意外后果(变量为空),并且会破坏现有代码。 所以不要这样做! 这些文档也需要更新以说明这一点。

语法

list($a, $b) = sscanf("hello world", "%s %s");

将按预期工作,并且在我注意到的 Apache 中似乎没有引起任何问题。
-4
sbarnum.pointsystems@com
21 年前
更多关于电话的乐趣! 这假设电话号码是 10 位数,只有数字数据,但可以轻松地先检查字符串的长度。

function formatPhone($phone) {
if (empty($phone)) return "";
sscanf($phone, "%3d%3d%4d", $area, $prefix, $exchange);
$out = @$area ? "($area) " : "";
$out .= $prefix . '-' . $exchange;
return $out;
}
-9
nmmm at nmmm dot nu
12 年前
这更像是 C/C++ 示例,但在 PHP 中也能正常工作。

<?php
$qs
= "index.php?id=34&name=john";

print_r( sscanf($qs, "%[^?]?%[^?]") );

$qs = "id=34&name=john";

print_r( sscanf($qs, "id=%[^&]&name=%[^&]") );
?>
-11
Igor Feghali
15 年前
解析具有固定字段大小的输入字符串,其中包含带有空格的数据

<?php
$result
= sscanf(" Vendor: My Vendo Model: Super Model Foo Rev: 1234",
' Vendor: %8[ -~] Model: %16[ -~] Rev: %4c',
$vendor, $model, $rev);
?>

$vendor => My Vendo
$model => Super Model Foo
$rev => 1234
To Top