搜索段落和 return 整个第一行,直到并包括整个最后一行,每行使用字符串关键字

Search Paragraph and return entire first line until and including entire last line using string keyword for each line

我正在尝试找到一种使用字符串作为起点来隔离特定段落的方法,其中字符串可以是行的任何部分(不一定是结尾或开头)中的单词。

因此它将抓取出现字符串的整行,然后抓取直到找到第二个字符串的那一行。我检查了各种问题,但没有找到我想要的。这是一个带有所需输出段落的示例输入段落:

输入:

JUNKTEXTJUNKTEXTJUNKTEXT
JUNKTEXTJUNKTEXTJUNKTEXTJUNKTEXT
NOTJUNK ABC NOTJUNK
DEF GHI JKL
MNO PQR STW
UVW XYZ NOTJUNK
JUNKTEXTJUNKTEXTJUNKTEXTJUNKTEXTJUNKTEXTJUNKTEXT
JUNKTEXTJUNKTEXT
JUNKTEXTJUNKTEXT

Objective:我想得到每一行从ABC(包括同一行ABC之前和ABC之后的词)到XYZ(包括XYZ前后的词)。 ABC 和 XYZ 在段落中始终只出现一次 - 而 ABC 将始终出现在 XYZ 之前。我的问题段落是从电子邮件中获取的,我目前正在使用 PhpMimeMailParser 来解析电子邮件。

开始字符串搜索词:ABC

结束字符串搜索词:XYZ

期望的输出:

NOTJUNK ABC NOTJUNK
DEF GHI JKL
MNO PQR STW
UVW XYZ NOTJUNK
startWord = "ABC"
endWord = "XYZ"
result = ""
foreach(word in para)
{
    if(word == startWord || result.Length > 0)
      result += word;
    if(word == endWord)
      break;
}
return result;

-- 如果序列多次出现则重复上述逻辑。


$data = "
JUNKTEXTJUNKTEXTJUNKTEXT
JUNKTEXTJUNKTEXTJUNKTEXTJUNKTEXT
ABC
DEF GHI JKL
MNO PQR STW
UVW XYZ
JUNKTEXTJUNKTEXTJUNKTEXTJUNKTEXTJUNKTEXTJUNKTEXT
JUNKTEXTJUNKTEXT
JUNKTEXTJUNKTEXT
";

$start = 'ABC';
$end = 'XYZ';

$startIndex = strpos($data, $start);
$endIndex = strpos($data, $end, $startIndex) + strlen($end);

$result = substr($data, $startIndex, $endIndex - $startIndex);

echo $result;

对于 case-insensitive 搜索,使用 stripos() 而不是 strpos()。

$data = "
JUNKTEXTJUNKTEXTJUNKTEXT
JUNKTEXTJUNKTEXTJUNKTEXTJUNKTEXT
ABC
DEF GHI JKL
MNO PQR STW
UVW XYZ
JUNKTEXTJUNKTEXTJUNKTEXTJUNKTEXTJUNKTEXTJUNKTEXT
JUNKTEXTJUNKTEXT
JUNKTEXTJUNKTEXT
";

$result = preg_replace('/(.*)(ABC.*XYZ)(.*)/s', '', $data);

echo $result;

对于 case-insensitivity 更改,在模式后添加正则表达式修饰符 i

'/(.*)(ABC.*XYZ)(.*)/si'

你可以使用这个:

$data = "
JUNKTEXTJUNKTEXTJUNKTEXT
JUNKTEXTJUNKTEXTJUNKTEXTJUNKTEXT
ABC
DEF GHI JKL
MNO PQR STW
UVW XYZ
JUNKTEXTJUNKTEXTJUNKTEXTJUNKTEXTJUNKTEXTJUNKTEXT
JUNKTEXTJUNKTEXT
JUNKTEXTJUNKTEXT
";

echo substr($data, strpos($data, "ABC"), strpos($data, "XYZ")-62+strlen("XYZ"));

您需要从索引 A 到索引 B 的字符串中获取数据。

strpos($data, "ABC") 是“ABC”字符串的索引。
strpos($data, "XYZ")-62+strlen("XYZ") 是您要使用的字符串的长度。要获得此长度,您需要从 strpos($data, "XYZ") 结果减去第一个结果并添加第二个搜索字符串的长度。为什么?因为 strpos() return 搜索值开始的索引。要结束你必须添加

这是我想出的解决方案。它不是很优雅,但它有效,我找不到其他方法:

preg_match('/[^\n]*ABC[^\n]*/', $text, $matches, PREG_OFFSET_CAPTURE);
$start = $matches[0][1];
$text = substr($text, $start);

// the above finds the beginning position of the line in which ABC
is located, and does a substr to remove every line before and above ABC

// the below find the beginning position of the line in which XYZ is
 located, and then performs strpos to determine the position at the
end of that line. Another substr is performed to remove everything
after that position

preg_match('/[^\n]*XYZ[^\n]*/', $text, $matches2, PREG_OFFSET_CAPTURE);
$end = $matches2[0][1];
$end = strpos($text, PHP_EOL, $end);
$text = substr($text, 0, $end);



echo $text

很高兴我能提供帮助。这是显然按照您的规定执行的正则表达式:

 /.*(^.*ABC.*XYZ.*?[\r\n]).*/sm

这是一个正则表达式测试器 link:regex test

支持信息:

选项

需要多行选项 m,因为捕获需要从一行的开头开始,而不是字符串的开头。

需要单行选项 s 来忽略带点的换行符。

说明

所以以选项为上下文,表达式可以描述为:

Ignore all characters until a line is found with ABC anywhere within the line. Begin to capture all characters starting at the line which contains the first ABC. Continue the capture until XYZ is found in a line. Stop the capture at the first newline found on the line with the XYZ. Ignore the remaining characters in string. The lazy qualifier in .*? ensures the match stops at the first newline (following the XYZ). I removed the {1} from my original comment as it is unnecessary.