如何在两对#或多对#之间找到字符串。
要搜索的示例文字: 这是#important#,需要进一步阐述。记得在回家之前购买#milk#。
我希望结果如下:
重要
回家之前喝牛奶答案 0 :(得分:2)
您可以尝试此代码
<?php
$s = 'This is #important# and needs to elaborated further. Remember to buy #milk before coming home#';
for($i=0;$i<strlen($s);$i++)
if($s[$i] == "#") {
$i++;
$str="";
while($s[$i]!='#') {
echo $s[$i];
$i++;
}
echo '<br>';
};
?>
然后你会得到你的结果
重要
回家之前喝牛奶答案 1 :(得分:2)
create table t91
( id int auto_increment primary key,
thing varchar(1000) not null
);
insert t91(thing) values
('This is #important# and needs to elaborated further. Remember to buy #milk before coming home#'),
('This is #important# and needs to elaborated further. Remember to buy #milk home#'),
('This is #');
select id,thing,theCount
from
( SELECT id,thing,
ROUND (
(
LENGTH(thing)
- LENGTH( REPLACE ( thing, "#", "") )
) / LENGTH("#")
) AS theCount
FROM t91
) d
where d.theCount>1
-- 2 rows returned (id 1 and 2)
以上编辑使用了从This Answer
挖走的策略-- truncate table t91;
create table t91
( id int auto_increment primary key,
thing varchar(1000) not null
);
insert t91(thing) values
('This is #important# and needs to elaborated further. Remember to buy #milk before coming home#'),
('This is #important# and needs to elaborated further. Remember to buy #milk home#'),
('This is #'),
('This is #1# ... #2# ... #');
功能:
DROP FUNCTION IF EXISTS findInsideHashMarks;
DELIMITER $$
CREATE FUNCTION findInsideHashMarks(s VARCHAR(200),segments INT)
RETURNS VARCHAR(200)
BEGIN
DECLARE i,nextPos,i1,i2 INT;
DECLARE sOut VARCHAR(200);
SET i=0;
SET nextPos=1;
SET sOut='';
WHILE i<segments DO
-- LOCATE(substr,str,pos)
SET i1=LOCATE('#',s,nextPos);
IF i1>0 THEN
SET i1=i1+1;
SET nextPos=i1+1;
SET i2=LOCATE('#',s,nextPos);
IF i2>0 THEN
SET nextPos=i2+1;
SET i2=i2-1;
SET sOut=CONCAT(sOut,SUBSTRING(s,i1,i2-i1+1));
END IF;
END IF;
SET i=i+1;
IF i<segments THEN
SET sOut=CONCAT(sOut,',');
END IF;
END WHILE;
RETURN sOut;
END$$
DELIMITER ;
查询:
SELECT id,
SUBSTRING_INDEX(SUBSTRING_INDEX(segString, ',', n.digit+1), ',', -1) dummy
FROM
( select id,thing,theCount,cast(floor(theCount / 2) as unsigned) as segments,
findInsideHashMarks(thing,cast(floor(theCount / 2) as unsigned)) as segString
FROM
( SELECT id,thing,
ROUND (
( LENGTH(thing)
- LENGTH( REPLACE ( thing, "#", "") )
) / LENGTH("#")
) AS theCount
FROM t91
) d1
where d1.theCount>1
) d2
INNER JOIN
(SELECT 0 digit UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3) n
ON LENGTH(REPLACE(d2.segString, ',' , '')) <= LENGTH(d2.segString)-n.digit
ORDER BY d2.id,n.digit;
输出:
+----+-------------------------+
| id | dummy |
+----+-------------------------+
| 1 | important |
| 1 | milk before coming home |
| 2 | important |
| 2 | milk home |
| 4 | 1 |
| 4 | 2 |
+----+-------------------------+
集合(a,b,c)到行的数字突破受到了来自用户Answer的fthiella的启发(低估)。正如fthiella的答案中所指出的那样(或者没有明确表示),UNION
策略可以扩展为在#
个标记之间拾取10个或更多数据块。
另请注意Edit1底部的先前归因。
Edit2的函数和查询的分支,但使用永久帮助程序表来避免查询派生表UNION
中的n
。它最多支持100个#
段。使用先前的(Edit2)t91表和函数。
架构:
CREATE TABLE 4kTable
( -- a helper table of about 4k consecutive ints
id int auto_increment primary key,
thing int null
)engine=MyISAM;
insert 4kTable (thing) values (null),(null),(null),(null),(null),(null),(null),(null),(null);
insert 4kTable (thing) select thing from 4kTable;
insert 4kTable (thing) select thing from 4kTable;
insert 4kTable (thing) select thing from 4kTable;
insert 4kTable (thing) select thing from 4kTable;
insert 4kTable (thing) select thing from 4kTable;
insert 4kTable (thing) select thing from 4kTable;
insert 4kTable (thing) select thing from 4kTable;
insert 4kTable (thing) select thing from 4kTable;
insert 4kTable (thing) select thing from 4kTable;
-- verify:
-- select min(id),max(id),count(*) from 4kTable;
-- 1 4608 4608
ALTER TABLE 4kTable ENGINE = InnoDB; -- *********** it is now InnoDB
-- verify:
-- select min(id),max(id),count(*) from 4kTable;
-- 1 4608 4608
-- no innodb auto_increment gaps (consecutive block)
查询:
SELECT id,
SUBSTRING_INDEX(SUBSTRING_INDEX(segString, ',', n.digit+1), ',', -1) dummy
FROM
( select d1.id,thing,theCount,cast(floor(theCount / 2) as unsigned) as segments,
findInsideHashMarks(thing,cast(floor(theCount / 2) as unsigned)) as segString
FROM
( SELECT id,thing,
ROUND (
( LENGTH(thing)
- LENGTH( REPLACE ( thing, "#", "") )
) / LENGTH("#")
) AS theCount
FROM t91
) d1
where d1.theCount>1
) d2
INNER JOIN
(select id-1 as digit from 4kTable where id<=100) n
ON LENGTH(REPLACE(d2.segString, ',' , '')) <= LENGTH(d2.segString)-n.digit
ORDER BY d2.id,n.digit;
与Edit2 Output
部分相同的输出。我通常在一个系统中有一些永久的助手表,尤其是带有日期的left joins
。