我有一个存储在字符串中的html代码,例如:
$html = '
<html>
<body>
<p>Hello <em>進撃の巨人</em>!</p>
random code
random code
<p>Lorem <span>ipsum<span>.</p>
</body>
</html>
';
然后我在变量中存储了两个句子:
$begin = 'Hello 進撃の巨人!';
$end = 'Lorem ipsum.';
我想在$html
中搜索这两个句子,并在它们之前和之后删除所有内容。因此$html
将成为:
$html = 'Hello <em>進撃の巨人</em>!</p>
random code
random code
<p>Lorem <span>ipsum<span>.';
我怎样才能做到这一点?请注意,$begin
和$end
变量没有html标记,但$html
中的句子很可能包含如上所示的标记。
也许正则表达式方法?
strpos()
方法。问题是$html
在句子中包含标签,导致$begin
和$end
句子不匹配。在运行strip_tags($html)
之前我可以strpos()
,但是显然我会在没有标签的情况下结束$html
。
搜索变量的一部分,例如Hello
,但这绝不安全,会提供很多匹配。
答案 0 :(得分:12)
这是一个简短的,但我相信 - 基于惰性点匹配正则表达式的工作解决方案(可以通过创建更长的展开正则表达式来改进,但除非你有非常大的文本块,否则应该足够了。)< / p>
$html = "<html>\n<body>\n<p><p>H<div>ello</div><script></script> <em>進 撃の巨人</em>!</p>\nrandom code\nrandom code\n<p>Lorem <span>ipsum<span>.</p>\n</body>\n </html>";
$begin = 'Hello 進撃の巨人!';
$end = 'Lorem ipsum.';
$begin = preg_replace_callback('~\s++(?!\z)|(\s++\z)~u', function ($m) { return !empty($m[1]) ? '' : ' '; }, $begin);
$end = preg_replace_callback('~\s++(?!\z)|(\s++\z)~u', function ($m) { return !empty($m[1]) ? '' : ' '; }, $end);
$begin_arr = preg_split('~(?=\X)~u', $begin, -1, PREG_SPLIT_NO_EMPTY);
$end_arr = preg_split('~(?=\X)~u', $end, -1, PREG_SPLIT_NO_EMPTY);
$reg = "(?s)(?:<[^<>]+>)?(?:&#?\\w+;)*\\s*" . implode("", array_map(function($x, $k) use ($begin_arr) { return ($k < count($begin_arr) - 1 ? preg_quote($x, "~") . "(?:\s*(?:<[^<>]+>|&#?\\w+;))*" : preg_quote($x, "~"));}, $begin_arr, array_keys($begin_arr)))
. "(.*?)" .
implode("", array_map(function($x, $k) use ($end_arr) { return ($k < count($end_arr) - 1 ? preg_quote($x, "~") . "(?:\s*(?:<[^<>]+>|&#?\\w+;))*" : preg_quote($x, "~"));}, $end_arr, array_keys($end_arr)));
echo $reg .PHP_EOL;
preg_match('~' . $reg . '~u', $html, $m);
print_r($m[0]);
请参阅IDEONE demo
算法:
preg_split('~(?<!^)(?=\X)~u', $end)
)并通过添加匹配模式(?:<[^<>]+>)?
的可选标记来回填。 / LI>
(?s)
匹配包含换行符的任何字符时,.
启用DOTALL模式,而.*?
将匹配前导跟踪分隔符中的0+个字符。正则表达式详细信息:
'~(?<!^)(?=\X)~u
匹配每个字形之前的字符串开头以外的每个位置(?s)(?:<[^<>]+>)?(?:&#?\w+;)*\s*H(?:\s*(?:<[^<>]+>|&#?\w+;))*e(?:\s*(?:<[^<>]+>|&#?\w+;))*l(?:\s*(?:<[^<>]+>|&#?\w+;))*l(?:\s*(?:<[^<>]+>|&#?\w+;))*o(?:\s*(?:<[^<>]+>|&#?\w+;))* (?:\s*(?:<[^<>]+>|&#?\w+;))*進(?:\s*(?:<[^<>]+>|&#?\w+;))*撃(?:\s*(?:<[^<>]+>|&#?\w+;))*の(?:\s*(?:<[^<>]+>|&#?\w+;))*巨(?:\s*(?:<[^<>]+>|&#?\w+;))*人(?:\s*(?:<[^<>]+>|&#?\w+;))*\!(?:\s*(?:<[^<>]+>|&#?\w+;))*
+ (.*?)
+ L(?:\s*(?:<[^<>]+>|&#?\w+;))*o(?:\s*(?:<[^<>]+>|&#?\w+;))*r(?:\s*(?:<[^<>]+>|&#?\w+;))*e(?:\s*(?:<[^<>]+>|&#?\w+;))*m(?:\s*(?:<[^<>]+>|&#?\w+;))* (?:\s*(?:<[^<>]+>|&#?\w+;))*i(?:\s*(?:<[^<>]+>|&#?\w+;))*p(?:\s*(?:<[^<>]+>|&#?\w+;))*s(?:\s*(?:<[^<>]+>|&#?\w+;))*u(?:\s*(?:<[^<>]+>|&#?\w+;))*m(?:\s*(?:<[^<>]+>|&#?\w+;))*\.
- 带有可选子模式的前导和尾随分隔符,用于标记匹配和(.*?)
(捕获可能不是必需的) )里面。~u
修饰符是必需的,因为要处理Unicode字符串。begin
和end
模式中的任何空格都可以替换为\s+
子模式,以匹配任何类型的输入字符串中有1个以上的空白字符。$begin = preg_replace('~\s+~u', ' ', $begin);
和$end = preg_replace('~\s+~u', ' ', $end);
来计算输入字符串中的1 +空格。&#?\\w+;
,它还将匹配
和{
个实体。它还附加\s*
以匹配可选空格,并使用*
进行量化(可以为零或更多)。答案 1 :(得分:8)
我真的想写一个正则表达式解决方案。但我之前有一些很好的复杂解决方案。所以,这是一个非正则表达式解决方案。
简短说明:主要问题是保留HTML标记。如果HTML标签被剥离,我们可以轻松搜索文本。所以:脱掉这些!我们可以轻松搜索剥离的内容,并生成我们想要剪切的子字符串。然后,尝试在保留标记的同时从HTML中剪切此子字符串。
<强>优点:强>
此方案的静态实用程序类:
class HtmlExtractUtil
{
const FAKE_MARKUP = '<>';
const MARKUP_PATTERN = '#<[^>]+>#u';
static public function extractBetween($html, $startTextToFind, $endTextToFind)
{
$strippedHtml = preg_replace(self::MARKUP_PATTERN, '', $html);
$startPos = strpos($strippedHtml, $startTextToFind);
$lastPos = strrpos($strippedHtml, $endTextToFind);
if ($startPos === false || $lastPos === false) {
return "";
}
$endPos = $lastPos + strlen($endTextToFind);
if ($endPos <= $startPos) {
return "";
}
return self::extractSubstring($html, $startPos, $endPos);
}
static public function extractSubstring($html, $startPos, $endPos)
{
preg_match_all(self::MARKUP_PATTERN, $html, $matches, PREG_OFFSET_CAPTURE);
$start = -1;
$end = -1;
$previousEnd = 0;
$stripPos = 0;
$matchArray = $matches[0];
$matchArray[] = [self::FAKE_MARKUP, strlen($html)];
foreach ($matchArray as $match) {
$diff = $previousEnd - $stripPos;
$textLength = $match[1] - $previousEnd;
if ($start == (-1)) {
if ($startPos >= $stripPos && $startPos < $stripPos + $textLength) {
$start = $startPos + $diff;
}
}
if ($end == (-1)) {
if ($endPos > $stripPos && $endPos <= $stripPos + $textLength) {
$end = $endPos + $diff;
break;
}
}
$tagLength = strlen($match[0]);
$previousEnd = $match[1] + $tagLength;
$stripPos += $textLength;
}
if ($start == (-1)) {
return "";
} elseif ($end == (-1)) {
return substr($html, $start);
} else {
return substr($html, $start, $end - $start);
}
}
}
<强>用法:强>
$html = '
<html>
<body>
<p>Any string before</p>
<p>Hello <em>進撃の巨人</em>!</p>
random code
random code
<p>Lorem <span>ipsum<span>.</p>
<p>Any string after</p>
</body>
</html>
';
$startTextToFind = 'Hello 進撃の巨人!';
$endTextToFind = 'Lorem ipsum.';
$extractedText = HtmlExtractUtil::extractBetween($html, $startTextToFind, $endTextToFind);
header("Content-type: text/plain; charset=utf-8");
echo $extractedText . "\n";
答案 2 :(得分:7)
正则表达式在解析HTML时有其局限性。像许多人在我之前所做的那样,我将参考这个famous answer。
例如,假设此标记出现在必须提取的部分之前的HTML中:
<p attr="Hello 進撃の巨人!">This comes before the match</p>
许多正则表达式解决方案会偶然发现这一点,并返回一个从此开始p
标记中间开始的字符串。
或者考虑HTML部分中必须匹配的注释:
<!-- Next paragraph will display "Lorem ipsum." -->
或者,出现一些松散的小于和大于标志(让我们在评论或属性值中说):
<!-- Next paragraph will display >-> << Lorem ipsum. >> -->
<p data-attr="->->->" class="myclass">
这些正则表达式会对此做些什么?
这些只是示例......无数其他情况会给基于正则表达式的解决方案带来问题。
有更可靠的方法来解析HTML。
我将在此处建议使用此算法基于DOMDocument接口的解决方案:
获取HTML文档的文本内容,并确定两个子字符串(开头/结尾)所在的偏移量。
然后浏览DOM文本节点,跟踪这些节点所适合的偏移量。在两个边界偏移中的任何一个相交的节点中,插入预定义的分隔符(|
)。该分隔符不应出现在HTML字符串中。因此,在满足条件之前,它会加倍(||
,||||
,...);
最后通过此分隔符拆分HTML表示,并将中间部分作为结果提取。
以下是代码:
function extractBetween($html, $begin, $end) {
$dom = new DOMDocument();
// Load HTML in DOM, making sure it supports UTF-8; double HTML tags are no problem
$dom->loadHTML('<html><head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
</head></html>' . $html);
// Get complete text content
$text = $dom->textContent;
// Get positions of the beginning/ending text; exit if not found.
if (($from = strpos($text, $begin)) === false) return false;
if (($to = strpos($text, $end, $from + strlen($begin))) === false) return false;
$to += strlen($end);
// Define a non-occurring delimiter by repeating `|` enough times:
for ($delim = '|'; strpos($html, $delim) !== false; $delim .= $delim);
// Use XPath to traverse the DOM
$xpath = new DOMXPath($dom);
// Go through the text nodes keeping track of total text length.
// When exceeding one of the two offsets, inject a delimiter at that position.
$pos = 0;
foreach($xpath->evaluate("//text()") as $node) {
// Add length of node's text content to total length
$newpos = $pos + strlen($node->nodeValue);
while ($newpos > $from || ($from === $to && $newpos === $from)) {
// The beginning/ending text starts/ends somewhere in this text node.
// Inject the delimiter at that position:
$node->nodeValue = substr_replace($node->nodeValue, $delim, $from - $pos, 0);
// If a delimiter was inserted at both beginning and ending texts,
// then get the HTML and return the part between the delimiters
if ($from === $to) return explode($delim, $dom->saveHTML())[1];
// Delimiter was inserted at beginning text. Now search for ending text
$from = $to;
}
$pos = $newpos;
}
}
你会这样称呼:
// Sample input data
$html = '
<html>
<body>
<p>This comes before the match</p>
<p>Hey! Hello <em>進撃の巨人</em>!</p>
random code
random code
<p>Lorem <span>ipsum<span>. la la la</p>
<p>This comes after the match</p>
</body>
</html>
';
$begin = 'Hello 進撃の巨人!';
$end = 'Lorem ipsum.';
// Call
$html = extractBetween($html, $begin, $end);
// Output result
echo $html;
输出:
Hello <em>進撃の巨人</em>!</p>
random code
random code
<p>Lorem <span>ipsum<span>.
您会发现此代码也比正则表达式更容易维护。
在eval.in上看到它。
答案 3 :(得分:5)
到目前为止,这可能不是最佳解决方案,但我喜欢开头讨论这样的&#34;谜语&#34;,所以这就是我的方法。
<?php
$subject = ' <html>
<body>
<p>He<i>l</i>lo <em>Lydia</em>!</p>
random code
random code
<p>Lorem <span>ipsum</span>.</p>
</body>
</html>';
$begin = 'Hello Lydia!';
$end = 'Lorem ipsum.';
$begin_chars = str_split($begin);
$end_chars = str_split($end);
$begin_re = '';
$end_re = '';
foreach ($begin_chars as $c) {
if ($c == ' ') {
$begin_re .= '(\s|(<[a-z/]+>))+';
}
else {
$begin_re .= $c . '(<[a-z/]+>)?';
}
}
foreach ($end_chars as $c) {
if ($c == ' ') {
$end_re .= '(\s|(<[a-z/]+>))+';
}
else {
$end_re .= $c . '(<[a-z/]+>)?';
}
}
$re = '~(.*)((' . $begin_re . ')(.*)(' . $end_re . '))(.*)~ms';
$result = preg_match( $re, $subject , $matches );
$start_tag = preg_match( '~(<[a-z/]+>)$~', $matches[1] , $stmatches );
echo $stmatches[1] . $matches[2];
输出:
<p>He<i>l</i>lo <em>Lydia</em>!</p>
random code
random code
<p>Lorem <span>ipsum</span>.</p>
这符合这种情况,但我认为需要更多逻辑来逃避正则表达式特殊字符,例如句号。
一般来说,这个代码片段的作用是什么:
Hello
也需要匹配Hel<i>l</i>o
。(<[a-z/]+>)?
,其中包含空格字符的特殊情况。答案 4 :(得分:4)
你可以试试这个RegEx:
2nd
代替 (.*?)(H.*?e.*?l.*?l.*?o.*?\s(<.*?>)*進.*?撃.*?の.*?巨.*?人.*?(<\/.*?>)*(.*?)(<.*?>)*L.*?o.*?r.*?e.*?m.*?\s(<.*?>)*i.*?p.*?s.*?u.*?m.*?)(.*)
捕获群
正则表达式可缩短为:
docker build -t opencv:2.4.11 .
答案 5 :(得分:4)
只是为了好玩
<?php
$begin = 'Hello Moto!';
$end = 'Lorem ipsum.';
//https://regex101.com/r/mC8aO6/1
$re = "/[\\w\\W]/";
$str = $begin.$end;
$subst = "$0.*?";
$result = preg_replace($re, $subst, $str);
//Hello Moto!
//to
//H.*?e.*?l.*?l.*?o.*? .*?M.*?o.*?t.*?o.*?!.*?
//https://regex101.com/r/fS6zG2/1
$re = "/(\\!|\\.\\.)/";
$str = $result;
$subst = "\\\\$1";
$result = preg_replace($re, $subst, $str);
$re = "/.*(<p.*?$result.*?p>).*/s";
$str = " <html>\n <body>\n <p>He<i>l</i>lo <em>Moto</em>!\n random code\n random code\n <p>Lorem <span>ipsum<span>.<p>\n </body>\n </html>\n ";
$subst = "$1";
$result = preg_replace($re, $subst, $str);
echo $result."\n";
?>
输入
$begin = 'Hello Moto!';
$end = 'Lorem ipsum.';
<html>
<body>
<p>He<i>l</i>lo <em>Moto</em>!
random code
random code
<p>Lorem <span>ipsum<span>.<p>
</body>
</html>
输出
<p>He<i>l</i>lo <em>Moto</em>!
random code
random code
<p>Lorem <span>ipsum<span>.<p>
答案 6 :(得分:4)
这个怎么样?
$escape=array('\\'=>1,'^'=>1,'?'=>1,'+'=>1,'*'=>1,'{'=>1,'}'=>1,'('=>1,')'=>1,'['=>1,']'=>1,'|'=>1,'.'=>1,'$'=>1,'+'=>1,'/'=>1);
$pattern='/';
for($i=0;isset($begin[$i]);$i++){
if(ord($c=$begin[$i])<0x80||ord($c)>0xbf){
if(isset($escape[$c]))
$pattern.="([ \t\r\n\v\f]*<\\/?[a-zA-Z]+>[ \t\r\n\v\f]*)*\\$c";
else
$pattern.="([ \t\r\n\v\f]*<\\/?[a-zA-Z]+>[ \t\r\n\v\f]*)*$c";
}
else
$pattern.=$c;
}
$pattern.="(.|\n|\r)*";
for($i=0;isset($end[$i]);$i++){
if(ord($c=$end[$i])<0x80||ord($c)>0xbf){
if(isset($escape[$c]))
$pattern.="([ \t\r\n\v\f]*<\\/?[a-zA-Z]+>[ \t\r\n\v\f]*)*\\$c";
else
$pattern.="([ \t\r\n\v\f]*<\\/?[a-zA-Z]+>[ \t\r\n\v\f]*)*$c";
}
else
$pattern.=$c;
}
$pattern[17]='?';
$pattern.='(<\\/?[a-zA-Z]+>)?/';
preg_match($pattern,$html,$a);
$match=$a[0];
答案 7 :(得分:4)
在HTML源上进行内容搜索有几种不同的方法。它们都有优点和缺点。如果未知代码中的结构是一个问题,最安全的方法是使用XML解析器,但是,这些是复杂的,因此相当慢。
正则表达式专为文本处理而设计。尽管由于开销而使用正则表达式并不是最快的,但preg_
函数是一种合理的折衷方案,可以保持代码小而简洁,同时只有在防止模式变得过于复杂时才会对性能产生很大的影响。
通过递归正则表达式可以分析HTML结构。由于处理速度变慢并且难以调试,我更喜欢在PHP中编写基本逻辑代码,并利用preg_
函数执行较小的快速任务。
这是OOP中的一个解决方案,一个用于处理同一HTML源上的许多搜索的小类。它已经是一种处理扩展类似问题的方法,例如在下一个标记边界之前添加前一个和后一个内容。它并不是一个完美的解决方案,但它很容易扩展。
逻辑是:
为初始化支付一些运行时间来存储相对于纯文本的标签位置,剥离标签并将字符串存储在<...>
和长度之和之间。
然后在每个内容搜索上匹配具有普通内容的针。通过二进制搜索在HTML源代码中找到开始/结束位置。
二进制搜索的工作方式如下:需要排序列表。您存储第一个和最后一个元素的索引+ 1。通过加法和整数除以2来计算平均值。通过右位移来执行除法和除法。如果找到的值为低,则将较小的索引var设置为当前索引,否则设置较大的索引var。停止索引差异1.如果搜索确切的值,请在找到的元素上提前中断。 0,(14 + 1)=&gt; 7; 7,15 =&gt; 11; 7,11 =&gt; 9; 7,9 =&gt; 8; 8-7 = diff.1 而不是15次迭代,只完成了4次。起始值越大,指数保存的时间就越多。
PHP类:
<?php
class HtmlTextSearch
{
protected
$html = '',
$heystack = '',
$tags = [],
$current_tag_idx = null
;
const
RESULT_NO_MODIFICATION = 0,
RESULT_PREPEND_TAG = 1,
RESULT_PREPEND_TAG_CONTENT = 2,
RESULT_APPEND_TAG = 4,
RESULT_APPEND_TAG_CONTENT = 8,
MATCH_CASE_INSENSITIVE =16,
MATCH_BLANK_AS_WHITESPACE =32,
MATCH_BLANK_MULTIPLE =64
;
public function __construct($html)
{
$this->set_html($html);
}
public function set_html($html)
{
$this->html = $html;
$regexp = '~<.*?>~su';
preg_match_all($regexp, $html, $this->tags, PREG_PATTERN_ORDER | PREG_OFFSET_CAPTURE);
$this->tags = $this->tags[0];
# we use exact the same algorithm to strip html
$this->heystack = preg_replace($regexp, '', $html);
# convert positions to plain content
$sum_length = 0;
foreach($this->tags as &$tag)
{ $tag['pos_in_content'] = $tag[1] - $sum_length;
$tag['sum_length' ] = $sum_length += strlen($tag[0]);
}
# zero length dummy tags to mark start/end position of strings not beginning/ending with a tag
array_unshift($this->tags , [0 => '', 1 => 0, 'pos_in_content' => 0, 'sum_length' => 0 ]);
array_push ($this->tags , [0 => '', 1 => strlen($html)-1]);
}
public function translate_pos_plain2html($content_position)
{
# binary search
$idx = [true => 0, false => count($this->tags)-1];
while(1 < $idx[false] - $idx[true])
{ $i = ($idx[true] + $idx[false]) >>1; // integer half of both array indexes
$idx[$this->tags[$i]['pos_in_content'] <= $content_position] = $i; // hold one index less and the other greater
}
$this->current_tag_idx = $idx[true];
return $this->tags[$this->current_tag_idx]['sum_length'] + $content_position;
}
public function &find_content($needle_start, $needle_end = '', $result_modifiers = self::RESULT_NO_MODIFICATION)
{
$needle_start = preg_quote($needle_start, '~');
$needle_end = '' == $needle_end ? '' : preg_quote($needle_end , '~');
if((self::MATCH_BLANK_MULTIPLE | self::MATCH_BLANK_AS_WHITESPACE) & $result_modifiers)
{
$replacement = self::MATCH_BLANK_AS_WHITESPACE & $result_modifiers ? '\s' : ' ';
if(self::MATCH_BLANK_MULTIPLE & $result_modifiers)
{ $replacement .= '+';
$multiplier = '+';
}
else
$multiplier = '';
$repl_pattern = "~ $multiplier~";
$needle_start = preg_replace($repl_pattern, $replacement, $needle_start);
$needle_end = preg_replace($repl_pattern, $replacement, $needle_end);
}
$icase = self::MATCH_CASE_INSENSITIVE & $result_modifiers ? 'i' : '';
$search_pattern = "~{$needle_start}.*?{$needle_end}~su$icase";
preg_match_all($search_pattern, $this->heystack, $matches, PREG_PATTERN_ORDER | PREG_OFFSET_CAPTURE);
foreach($matches[0] as &$match)
{ $pre = $post = '';
$pos_start = $this->translate_pos_plain2html($match[1]);
if(self::RESULT_PREPEND_TAG_CONTENT & $result_modifiers)
$pos_start = $this->tags[$this->current_tag_idx][1]
+( self::RESULT_PREPEND_TAG & $result_modifiers ? 0 : strlen ($this->tags[$this->current_tag_idx][0]) );
elseif(self::RESULT_PREPEND_TAG & $result_modifiers)
$pre = $this->tags[$this->current_tag_idx][0];
$pos_end = $this->translate_pos_plain2html($match[1] + strlen($match[0]));
if(self::RESULT_APPEND_TAG_CONTENT & $result_modifiers)
{ $next_tag = $this->tags[$this->current_tag_idx+1];
$pos_end = $next_tag[1]
+( self::RESULT_APPEND_TAG & $result_modifiers ? strlen ($next_tag[0]) : 0);
}
elseif(self::RESULT_APPEND_TAG & $result_modifiers)
$post = $this->tags[$this->current_tag_idx+1][0];
$match = $pre . substr($this->html, $pos_start, $pos_end - $pos_start) . $post;
};
return $matches[0];
}
}
某些测试用例:
$html_source = get($_POST['html'], <<< ___
<html>
<body>
<p>He said: "Hello <em>進撃の巨人</em>!"</p>
random code
random code
<p>Lorem <span>ipsum</span>. foo bar</p>
</body>
</html>
___
);
function get(&$ref, $default=null) { return isset($ref) ? $ref : $default; }
function attr_checked($name, $method = "post")
{ $req = ['post' => '_POST', 'get' => '_GET'];
return isset($GLOBALS[$req[$method]][$name]) ? ' checked="checked"' : '';
}
$begin = get($_POST['begin'], '"Hello 進撃の巨人!"');
$end = get($_POST['end' ], 'Lorem ipsum.' );
?>
<form action="" method="post">
<textarea name="html" cols="80" rows="10"><?php
echo $html_source;
?></textarea>
<br><input type="text" name="begin" value="<?php echo $begin;?>">
<br><input type="text" name="end" value="<?php echo $end ;?>">
<br><input type="checkbox" name="tag-pre" id="tag-pre"<?php echo attr_checked('tag-pre');?>>
<label for="tag-pre">prefix tag</label>
<br><input type="checkbox" name="txt-pre" id="txt-pre"<?php echo attr_checked('txt-pre');?>>
<label for="txt-pre">prefix content</label>
<br><input type="checkbox" name="txt-suf" id="txt-suf"<?php echo attr_checked('txt-suf');?>>
<label for="txt-suf">suffix content</label>
<br><input type="checkbox" name="tag-suf" id="tag-suf"<?php echo attr_checked('tag-suf');?>>
<label for="tag-suf">suffix tag</label>
<br>
<br><input type="checkbox" name="wspace" id="wspace"<?php echo attr_checked('wspace');?>>
<label for="wspace">blanc (#32) matches any whitespace character</label>
<br><input type="checkbox" name="multiple" id="wspace"<?php echo attr_checked('multiple');?>>
<label for="multiple">one or more blancs match any number of blancs/whitespaces</label>
<br><input type="checkbox" name="icase" id="icase"<?php echo attr_checked('icase');?>>
<label for="icase">case insensitive</label>
<br><button type="submit">submit</button>
</form>
<?php
$html = new HtmlTextSearch($html_source);
$opts=
[ 'tag-pre' => HtmlTextSearch::RESULT_PREPEND_TAG,
'txt-pre' => HtmlTextSearch::RESULT_PREPEND_TAG_CONTENT,
'txt-suf' => HtmlTextSearch::RESULT_APPEND_TAG_CONTENT,
'tag-suf' => HtmlTextSearch::RESULT_APPEND_TAG,
'wspace' => HtmlTextSearch::MATCH_BLANK_AS_WHITESPACE,
'multiple'=> HtmlTextSearch::MATCH_BLANK_MULTIPLE,
'icase' => HtmlTextSearch::MATCH_CASE_INSENSITIVE
];
$options = 0;
foreach($opts as $k => $v)
if(isset($_POST[$k]))
$options |= $v;
$results = $html->find_content($begin, $end, $options);
var_dump($results);
?>
答案 8 :(得分:2)
index(zamkniecie3) <- as.Date(index(zamkniecie3))
#MERGE! into one
all.in.one <- merge(zamkniecie1, zamkniecie2, zamkniecie3)
$html = '
<html>
<body>
<p>Hello <em>進撃の巨人</em>!</p>
random code
random code
<p>Lorem <span>ipsum<span>.</p>
</body>
</html>
';
$begin = 'Hello 進撃の巨人!';
$end = 'Lorem ipsum.';
$matchHtmlTag = '(?:<.*?>)?';
$matchAllNonGreedy = '(?:.|\r?\n)*?';
$matchUnescapedCharNotAtEnd = '([^\\\\](?!$)|\\.(?!$))';
$matchBeginWithTags = preg_replace(
$matchUnescapedCharNotAtEnd, '$0' . $matchHtmlTag, preg_quote($begin));
$matchEndWithTags = preg_replace(
$matchUnescapedCharNotAtEnd, '$0' . $matchHtmlTag, preg_quote($end));
$pattern = '/' . $matchBeginWithTags . $matchAllNonGreedy . $matchEndWithTags . '/';
preg_match($pattern, $html, $matches);
$html = $matches[0];
答案 9 :(得分:2)
假设您的示例中的random code
位于<p></p>
内,我建议您使用domdocument和xpath而不是正则表达式。
$html = '
<html>
<body>
<div>nada blahhh <p>test paragraph</p> <em>blahh</em></div>
<p>test</p>
<span>this is test</span>
<p>Hello <em>進撃の巨人</em>!</p>
<p>random code</p>
<p>random code</p>
<p>Lorem <span>ipsum<span>.</p>
<div>nada blahhh <p>test paragraph</p> <em>blahh</em></div>
<p>test</p>
<span>this is test</span>
</body>
</html>
';
$begin = 'Hello 進撃の巨人!';
$begin = iconv ( 'iso-8859-1','utf-8' , $begin ); // had to use iconv it won't be needed in your case
$end = 'Lorem ipsum.';
$doc = new DOMDocument();
$doc->loadHTML($html);
$xpath = new DOMXpath($doc);
// example 3: same as above with wildcard
$elements = $xpath->query("*/p");
if (!is_null($elements)) {
$flag = 'no_output';
foreach ($elements as $element) {
if($flag=='prepare_for_output'){$flag='output';}
if($element->nodeValue==$begin){
$flag='prepare_for_output';
}
if($element->nodeValue==$end){
$flag='no_output';
}
if($flag=='output') {
echo $element->nodeValue."\n";
}
}
}
http://sandbox.onlinephpfunctions.com/code/fa1095d98c6ef5c600f7b06366b4e0c4798a112f
答案 10 :(得分:2)
你可以使用这个概念,代码如下:
<html lang="en-US">
<head>
<title>HTML Unicode UTF-8</title>
<meta charset="utf-8">
</head>
<body>
<?php
$html = '
<html>
<body>
<p>Hello <em>進撃の巨人</em>!</p>
random code
random code
<p>Lorem <span>ipsum<span>.</p>
</body>
</html>
';
$begin = 'Hello 進撃の巨人!';
$end = 'Lorem ipsum.';
$stripped =strip_tags($html);
if (strpos($stripped, $end) !== false) {
$final =str_replace($begin,"",$stripped);
echo str_replace($end,"",$final);
}
?>
</body>
</html>
答案 11 :(得分:1)
不要试图使用正则表达式。
使用PHP的DOM库:http://php.net/manual/en/book.dom.php
<?php
header('Content-Type: text/html; charset=UTF-8');
$html = '
<html>
<body>
<p>Hello <em>進撃の巨人</em>!</p>
random code
random code
<p>Lorem <span>ipsum<span>.</p>
</body>
</html>
';
$doc = new DOMDocument();
$doc->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
$body_elements = $doc->getElementsByTagName("body");
$code = '';
foreach ($body_elements as $element) {
$children = $element->childNodes;
foreach ($children as $child)
{
$code.= $element->ownerDocument->saveHTML($child);
}
}
echo $code;
?>
如果您在php示例文件中运行该代码,则应使用&#34;查看源代码&#34;来检查网页的来源。在浏览器中查看html标签。 &lt; p&gt;或者&lt; em&gt;应该在那里; - )