我使用PHP的preg_match_all()来搜索使用file_get_contents()导入的字符串。正则表达式返回匹配,但我想知道在哪个行号找到这些匹配。实现这一目标的最佳技术是什么?从preg_match_all()获取行号
我可以读取文件作为数组,并为每一行执行正则表达式,但问题是我的正则表达式匹配回车(新行)的结果。
我使用PHP的preg_match_all()来搜索使用file_get_contents()导入的字符串。正则表达式返回匹配,但我想知道在哪个行号找到这些匹配。实现这一目标的最佳技术是什么?从preg_match_all()获取行号
我可以读取文件作为数组,并为每一行执行正则表达式,但问题是我的正则表达式匹配回车(新行)的结果。
好吧,它有点晚了,也许你alrady解决了这个问题,但我必须这样做,它很简单。 使用PREG_OFFSET_CAPTURE
标志preg_match
将返回匹配的字符位置。 让我们假设$ charpos,所以
list($before) = str_split($content, $charpos); // fetches all the text before the match
$line_number = strlen($before) - strlen(str_replace("\n", "", $before)) + 1;
voilá!
你不能这样做只有正则表达式。至少不干净。你能做些什么来使用preg_match_all的PREG_OFFSET_CAPTURE
标志并对整个文件进行后分析。
我的意思是你有匹配的字符串数组,并开始偏移每个字符串后仅数\r\n
或\n
或\r
有多少文件开始,每场比赛的偏移之间。匹配的行号将是不同EOL终止符的数量(\r\n
| \n
| \r
)加上1
。
我想,首先,你需要阅读$字符串到一个数组,每个元素代表每一行,也不要这个样子:
$List=file($String);
for($i=0;$i<count($List),$i++){
if(preg_match_all()){;//your work here
echo $i;//echo the line number where the preg_match_all() works
}
}
我想你错过了我的问题的这一部分:我可以读取文件作为数组,并为每一行执行正则表达式,但问题是我的正则表达式匹配回车(新行)的结果。 – bart 2017-07-31 20:00:35
你有一对夫妇的选择,但没有是 “简单”:
一个)exec()
和使用该系统grep
命令,该命令可以报告行号:使用在文件中
exec("grep -n 'your pattern here' file.txt", $output);`
b)中啜食,将其拆分为一行数组,然后使用preg_grep()
来查找匹配的行。
$dat = file_get_contents('file.txt');
$lines = explode($dat, "\n");
$matches = preg_grep('/your pattern here/', $lines);
c)以行大小块读取文件,保持行数,并在每行上进行模式匹配。
$fh = fopen('file.txt', 'rb');
$line = 1;
while ($line = fgets($fh)) {
if (preg_match('/your pattern here/', $line)) {
... whatever you need to do with matching lines ...
}
$line++;
}
每个人都有其跌宕起伏
一)你调用外部程序,如果你的模式包含任何用户提供的数据,你可能自己开到外壳当量一个SQL注入攻击。另一方面,你不必在整个文件中啜泣,并且会节省一些内存开销。
b)您可以安全地使用shell注入攻击,但是您必须在整个文件中啜泣。如果你的文件很大,你可能会耗尽可用的内存。
c)你每行调用一个正则表达式,如果你处理大量的行,这会产生大量的开销。
您可以使用preg_match_all查找每个换行的偏移量,然后将它们与您已有的偏移量进行比较。
// read file to buffer
$data = file_get_contents($datafile);
// find all linefeeds in buffer
$reg = preg_match_all("/\n/", $data, $lfall, PREG_OFFSET_CAPTURE);
$lfs = $lfall[0];
// create an array of every offset
$linenum = 1;
$offset = 0;
foreach($lfs as $lfrow)
{
$lfoffset = intval($lfrow[1]);
for(; $offset <= $lfoffset; $offset++)
$offsets[$offset] = $linenum; // offset => linenum
$linenum++;
}
这可行,但在每一行都会执行新的preg_match_all
,这可能会非常昂贵。
$file = file.txt;
$log = array();
$line = 0;
$pattern = '/\x20{2,}/';
if(is_readable($file)){
$handle = fopen($file, 'rb');
if ($handle) {
while (($subject = fgets($handle)) !== false) {
$line++;
if(preg_match_all ($pattern, $subject, $matches)){
$log[] = array(
'str' => $subject,
'file' => realpath($file),
'line' => $line,
'matches' => $matches,
);
}
}
if (!feof($handle)) {
echo "Error: unexpected fgets() fail\n";
}
fclose($handle);
}
}
另外,您可以读取该文件一旦哟得到的行号,然后对整个文件进行preg_match_all
和catpure的匹配偏移。
$file = 'file.txt';
$length = 0;
$pattern = '/\x20{2,}/';
$lines = array(0);
if(is_readable($file)){
$handle = fopen($file, 'rb');
if ($handle) {
$subject = "";
while (($line = fgets($handle)) !== false) {
$subject .= $line;
$lines[] = strlen($subject);
}
if (!feof($handle)) {
echo "Error: unexpected fgets() fail\n";
}
fclose($handle);
if($subject && preg_match_all ($pattern, $subject, $matches, PREG_OFFSET_CAPTURE)){
reset($lines);
foreach ($matches[0] as $key => $value) {
while(list($line, $length) = each($lines)){ // continues where we left off
if($value[1] < $length){
echo "match is on line: " . $line;
break; //break out of while loop;
}
}
}
}
}
}}
//Keep it simple, stupid
$allcodeline = explode(PHP_EOL, $content);
foreach ($allcodeline as $line => $val) :
if (preg_match("#SOMEREGEX#i",$val,$res)) {
echo $res[0] . '!' . $line . "\n";
}
endforeach;
$data = "Abba
Beegees
Beatles";
preg_match_all('/Abba|Beegees|Beatles/', $data, $matches, PREG_OFFSET_CAPTURE);
foreach (current($matches) as $match) {
$matchValue = $match[0];
$lineNumber = substr_count(mb_substr($data, 0, $match[1]), PHP_EOL) + 1;
echo "`{$matchValue}` at line {$lineNumber}\n";
}
输出
`Abba` at line 1
`Beegees` at line 2
`Beatles` at line 3
(请检查您的性能需求)
我要扔了一个猜测,说你可能不能够为此使用`preg_match_all`。 – drudge 2011-01-19 01:31:46
preg_split和结果中的行数?这听起来很蠢,现在我说了。 – scragz 2011-01-19 01:32:19
我没有看到任何简单的方法来完成你想要做的事... – 2011-01-19 01:36:21