我有一個文字檔
內容為
start
a1
b2
c3
d4
e5
show time
a1
b2
c3
d4
e5
show time
a1
b2
c3
d4
e5
end
假設我要抓取
start跟end 中間的文字
我有寫出來如下
<?php
$fn = fopen("a.txt","r");
$output = '';
$output_start = false;
while (true)
{
$buffer = fgets($fn);
flush();
if(strpos($buffer, "start") !== false) {
$output_start = true;
continue;
}
if(strpos($buffer, "end") !== false) {
break;
}
if($output_start) {
$output .= $buffer."<br>";
}
}
echo $output;
?>
執行結果是
a1
b2
c3
d4
e5
show time
a1
b2
c3
d4
e5
show time
a1
b2
c3
d4
e5
假設我想要程式看到第【2】個 show time 結束
理論上的結果應該是
a1
b2
c3
d4
e5
show time
a1
b2
c3
d4
e5
我把下面程式碼中的
【strpos】 換成 【strrpos】
【end】 換成 【show time】
if(strpos($buffer, "end") !== false) {
break;
}
改成
if(strrpos($buffer, "show time") !== false) {
break;
}
可是結果為
a1
b2
c3
d4
e5
請問大家要如何用 strpos 和 strrpos 來找出範圍呢
謝謝
因為你兩個都叫show time吧,
要不然你就是紀錄show time出現的次數,
等到第二次出現的時候再break;
這跟strpos
或strrpos
沒有關係
而是跟結束條件
的判斷有關係
結束條件是「第二個 showtime 出現」
所以就加一個變數 $had_one_showtime
第一次出現 showtime --> 把 $had_one_showtime 設為 true
第二次出現 showtime --> 結束處理,離開迴圈
<?php
$fn = fopen("a.txt","r");
$output = '';
$output_start = false;
$had_one_showtime = false;
while (true)
{
$buffer = fgets($fn);
flush();
if(strpos($buffer, "start") !== false) {
$output_start = true;
continue;
}
if(strpos($buffer, "show time") !== false) {
if ($had_one_showtime) {
break;
} else {
$had_one_showtime = true;
}
}
if($output_start) {
$output .= $buffer."<br>";
}
}
echo $output;
?>
推fillano大的解法~
另外提出用RegExp的解法給樓主參考
有些場合適用RegExp,前提是要略懂規則運算式語法,
以下是範例:
myfile.txt:
start
a1
b2
c3
d4
e5
show time
a1
b2
c3
d4
e5
show time
a1
b2
c3
d4
e5
end
php code:
<?php
$file = file_get_contents('myfile.txt');
printf("原始字串:<br/>%s<br/><hr/>", str_replace("\n","<br/>",$file));
?>
<?php
$file=str_replace("\n","<br/>",$file);
$re = "/(start)(.*?)(show time)(.*?)(show time)(.*?)(end)/";
$new_string = preg_replace($re, "\\4\\5\\6", $file);
$new_string=str_replace("<br/>","\n",$new_string);
printf("新的字串:<br/>%s<br/><hr/>", str_replace("\n","<br/>",$new_string));
?>
用資料庫,copy 進去,處理起來輕鬆愉快.
https://dev.mysql.com/doc/refman/8.0/en/load-data-local.html
-- 因為 8.0.2 以後 default 是關閉的,所以我們需要在 /etc/my.cnf
-- 設定 , 注意需要在 mysqld 區段裡
[mysqld]
local_infile=1
----------
-- 然後 restart mysqld, 使用新設定.
---------
-- client 登入時,也要指定啟用.
mysql -u miku1 -p --local-infile=1
-- 若 server 或 client 有一個沒啟用, 使用 LOAD DATA指令時會看到底下錯誤訊息
-- ERROR 1148 (42000): The used command is not allowed with this MySQL version
--
create table andy190514 (
id int unsigned not null auto_increment primary key
, txt varchar(100) not null
);
-- 注意到是將檔案放到 /tmp 目錄下,讓 mysql server 有權限讀取
LOAD DATA LOCAL INFILE '/tmp/andy190514.txt'
INTO TABLE andy190514
LINES TERMINATED BY '\n'
(txt);
--
select * from andy190514;
+----+-----------+
| id | txt |
+----+-----------+
| 1 | start |
| 2 | a1 |
| 3 | b2 |
| 4 | c3 |
| 5 | d4 |
| 6 | e5 |
| 7 | show time |
| 8 | a1 |
| 9 | b2 |
| 10 | c3 |
| 11 | d4 |
| 12 | e5 |
| 13 | show time |
| 14 | a1 |
| 15 | b2 |
| 16 | c3 |
| 17 | d4 |
| 18 | e5 |
| 19 | end |
+----+-----------+
19 rows in set (0.00 sec)
-- 有了 id, 要處理起來, 就很方便.
-- 資料量大的時候, 使用資料庫處理, 會比自行開發特定程式,更顯優勢.
以下請服用
$str = file_get_contents('myfile.txt');
preg_match_all('/start(.*?)show\stime+(.*?)show\stime+(.*?)+end/ies',$str,$ttt);
print_r($ttt);
echo '<br>';
echo $ttt[1][0]."\nshow time\n".$ttt[2][0]; //這是你要的結果
本想寫個萬用式的,懶的想了。