iT邦幫忙

0

【抓出文字檔的範圍】

我有一個文字檔
內容為
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 來找出範圍呢
謝謝

fillano iT邦超人 1 級 ‧ 2019-05-14 09:23:06 檢舉
一次把文字檔全部讀取,然後用分行符號切成陣列來處理(記得是用explode函數)。處理的時候記得先trim一下。這樣你在if裡面可以直接比較,不需要strpos之類。
ant1017 iT邦新手 4 級 ‧ 2019-05-14 09:26:54 檢舉
同意樓上用分行符號來切,這樣比較快,也不太會搞混...
犬千賀 iT邦新手 5 級 ‧ 2019-05-15 09:08:01 檢舉
同意
0
小魚
iT邦高手 1 級 ‧ 2019-05-14 09:25:40

因為你兩個都叫show time吧,
要不然你就是紀錄show time出現的次數,
等到第二次出現的時候再break;

小魚 iT邦高手 1 級 ‧ 2019-05-14 15:17:30 檢舉

另外說真的,
你改成strrpos完全沒有意義...
請先搞懂你的程式在寫什麼...

提示:
如果你是用fillano的方式全部讀回來,
也許還有用...

0
海綿寶寶
iT邦超人 1 級 ‧ 2019-05-14 09:45:14

這跟strposstrrpos沒有關係
而是跟結束條件的判斷有關係

結束條件是「第二個 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;
?>
1
ccutmis
iT邦高手 10 級 ‧ 2019-05-14 11:48:29

推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));
?>
2
一級屠豬士
iT邦高手 1 級 ‧ 2019-05-14 15:11:48

用資料庫,copy 進去,處理起來輕鬆愉快.
https://ithelp.ithome.com.tw/upload/images/20190514/20050647mR3kyww59B.jpg

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, 要處理起來, 就很方便.
-- 資料量大的時候, 使用資料庫處理, 會比自行開發特定程式,更顯優勢.
0
浩瀚星空
iT邦大師 1 級 ‧ 2019-05-14 16:27:15

以下請服用

$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]; //這是你要的結果

本想寫個萬用式的,懶的想了。

沒注意到 ccutmis 跟我的思考方式一樣。
他的比較好。
我是隨便寫寫處理的。

其實ccutmis可以不需要轉換成br
後置參數s就可以讓條件「.」萬用字符連帶判斷換行符了。
省下換來換去的麻煩

ccutmis iT邦高手 10 級 ‧ 2019-05-14 16:47:02 檢舉

/images/emoticon/emoticon12.gif

我要發表回答

立即登入回答