Search only the first column of a text file - php

I have a text file with the following contents:
---> 12455 ---> 125 ---> KKK
---> 11366 ---> 120 ---> LLL
---> 12477 ---> 120 ---> YYY
I am using the following PHP code to search the file for "---> 124" and I get the following results:
---> 12455 ---> 125 ---> KKK
---> 12477 ---> 120 ---> YYY
but I want the results to be like this:
---> 12455
---> 12477
I want it to return only the first column.
<?php
$file = 'mytext.txt';
$searchfor = '---> ' . "124";
// the following line prevents the browser from parsing this as HTML.
header('Content-Type: text/plain');
// get the file contents, assuming the file to be readable (and exist)
$contents = file_get_contents($file);
// escape special characters in the query
$pattern = preg_quote($searchfor, '/');
// finalise the regular expression, matching the whole line
$pattern = "/^.*$pattern.*\$/m";
// search, and store all matching occurences in $matches
if(preg_match_all($pattern, $contents, $matches)) {
echo implode($matches[0]);
} else {
echo "No matches found";
}
?>

Change your approach a little bit. Instead of storing the search term and separator in a single string, use two variables.
$sep = '--->';
$searchfor = '124';
$pattern = "/^$sep\s+($searchfor\d+)\s+.*/m";
// search, and store all matching occurences in $matches
if(preg_match_all($pattern, $contents, $matches)){
echo implode(' ', $matches[1])."\n";
}
Outputs:
12455 12477
Demo.

First of all, seperate your concerns:
Read the file
Parse the content
Search
Using Iterators, you can achieve something great here but it will need a deeper understanding of OOP and the iterator interface. What i'll recommend is a simpler approach:
<?php
//Read the file line by line
$handle = fopen('file.txt', 'r');
while(!foef($handle)){
$content = fgets($handle);
//Parse the line
$content = explode('---> ', $content);
//Analyse the line
if($content[1] == 124){
echo $content[0]."\n";
}
}
fclose($handle);
That should be it, just adapt it as you see it, i haven't tested the code here!

change "/^.*$pattern.*\$/m" to "/$pattern\d*/i"
and then echo implode($matches[0]); to foreach($matches[0] as $item) echo "$item<br />\r\n";

If the structure is always as you have shown, then:
Read the file line by line;
explode(); each line by space  ;
Read the element [1] of the result;
This seems to be most logical to me. No need for regex in here, because it will work slower then simple explode operation.
Here is an example:
$handle = fopen( 'file.txt', 'r' );
if ( $handle ) {
while ( ( $line = fgets( $handle ) ) !== false ) {
$matches = explode( ' ', $line );
if ( $matches[4] == '124' )
echo $matches[1] . '<br/>';
}
}

try this:
--->\s\d{5}
regex is overkill here, a simple explode('--->', $str) and selecting the first element would suffice

$file = file_get_contents('file.txt');
$lines = explode('---> ', $file);
for($i=1; $i<count($lines); $i=$i+3)
if(strpos($lines[$i], '124')!==false)
$col[$i/3] = /*'--> ' . */$lines[$i];
print_r($col);
That seems to work just fine. Uncomment the comment above if you want the --> included in the output. Also, the resulting $col array is indexed with the row number it is found. Just replace [$i/3] with [] if you don't want that.
Furthering this:
function SearchFileByColumn($contents, $col_num, $search, $col_count = 3) {
$segs = explode('---> ', $contents);
for($i=$col_num; $i<count($segs); $i=$i+$col_count)
if(strpos($segs[$i], $search) !== false)
$res[] = $segs[$i];
return $res;
}
$results = SearchFileByColumn($contents, 1, '124');

Related

Get text on next line of value found PHP

I have the following text file called people.txt with the contents:
mikey.mcgurk
Boss Man
michelle.mcgurk
Boss Man 2
I'd like to adjust my PHP script to grab the data on the line that follows each username, so if I was searching for mikey.mcgurk, my script would output Boss Man.
PHP:
<?php //
$file = 'people.txt';
$searchfor = "mikey.mcgurk";
// the following line prevents the browser from parsing this as HTML.
header('Content-Type: text/plain');
// get the file contents, assuming the file to be readable (and exist)
$contents = file_get_contents($file);
// escape special characters in the query
$pattern = preg_quote($searchfor, '/');
// finalise the regular expression, matching the whole line
$pattern = "/^.*$pattern.*\$/m";
// search, and store all matching occurences in $matches
if(preg_match_all($pattern, $contents, $matches)){
// write all of this to a text file
echo implode("\n", $matches[0]);
}
else{
echo "No matches found";
}
you can do like this
$contents = file_get_contents($file);
$contents = explode(PHP_EOL, $contents);
if(array_search($searchfor, $contents) !== false){
echo $contents[array_search($searchfor, $contents)+1];
}
You can compare like this:
$contents = file_get_contents($file);
$lines = explode("\n",$contents);
for($i = 0; $i < count($lines); $i++) {
if( $lines[$i] ==$searchfor ) {
echo "Username ".$lines[$i+1];
}
}
Instead of using regular expression you can do this by getting all lines in an array
$lines = explode(PHP_EOL, $contents);
then get keys of results
$keys = array_keys($lines, $pattern);
and increment keys by 1 to get the next line
foreach ($keys as $key) {
echo $lines[++$key];
}

Search and Replace Files in Directory

<span class="itemopener">82 top</span> <span class="allopener">all</span>
How can I change above to:
<span class="itemopener">top</span> <span class="allopener">82</span>
with PHP on an html file that contains around 30 of those HTML snippets.
Note: 82 can be any integer above 1.
Also, I want to run this script from a new file that I place in a directory, which will run the search and replace once for each of the 8000 HTML files in that directory (the script mustn't timeout before done - perhaps some feedback.)
i wrote function for replacement of the row:
function replace($row){
$replaced = preg_replace_callback("~(\<span class=\"itemopener\"\>)(\d{1,5})\s(top\</span\>.*\<span class=\"allopener\"\>).{3}(\</span\>)~iU", function($matches){
$str = $matches[1] . $matches[3] . $matches[2] . $matches[4];
return $str;
}, $row);
return $replaced;
}
$s = '<span class="itemopener">82 top</span> <span class="allopener">all</span>';
$replaced = replace($s);
echo "<pre>" . print_r($replaced, 1) . "</pre>";
exit();
Working demo of the function
If you would take file by one row, and do some simple check whether there is those spans you want to replace, then you can send them into this function..
But with number of files you specified, it will take some time.
For scanning of all files in path you can use my answer there: scandir
After little editing you can modify it to read only .htm files, and return to you what structure you desire..
Then you take all scanned htm files and process them with something like this:
$allScannedFiles = array("......");
foreach($allScannedFiles as $key => $path){
$file = file_get_contents($path);
$lines = explode(PHP_EOL, $file);
$modifiedFile = "";
foreach($lines as $line){
if(strpos($line, "span") && strpos($line, "itemopener")){
$line = replace($line);
}
$modifiedFile .= $line . PHP_EOL;
}
file_put_contents($path, $modifiedFile);
}
I wrote this one snippet from the head, so some testing is needed..
Then run it, go make yourself coffe and wait :)
If it will timeout, you can increase php timeout. How to do that is asked&answered here: how to increase timeout in php
alternatively you can try load files as DOMDocument and do replacements on that class documentation of DomDocument
But if in the files somewhere is not valid html, it may cause you problems..
I'm using the function created by #Jimmmy (replaced range d{2} by d{1,5} because "Note: 82 can be any integer above 1") and added the files search (tested it and works great) :
<?php
function replace($row){
$replaced = preg_replace_callback("~(\<span class=\"itemopener\"\>)(\d{1,5})\s(top\</span\>.*\<span class=\"allopener\"\>).{3}(\</span\>)~iU", function($matches){
$str = $matches[1] . $matches[3] . $matches[2] . $matches[4];
return $str;
}, $row);
return $replaced;
}
foreach ( glob( "*.html" ) as $file ) // GET ALL HTML FILES IN DIRECTORY.
{ $lines = file( $file ); // GET WHOLE FILE AS ARRAY OF STRINGS.
for ( $i = 0; $i < count( $lines ); $i++ ) // CHECK ALL LINES IN ARRAY.
$lines[ $i ] = replace( $lines[ $i ] ); // REPLACE PATTERN IF FOUND.
file_put_contents( $file,$lines ); // SAVE ALL ARRAY IN FILE.
}
?>

How to read a text file and search for a certain string before a colon and then show the content after the colon?

I have a file that contains something like this:
test:fOwimWPu0eSaNR8
test2:vogAqsfXpKzCfGr
I would like to be able to search the file for say test and it set the string after the : to a variable so it can be displayed, used etc.
Here is the code I have so far for finding 'test' in the file.
$file = 'file.txt';
$string = 'test';
$searchFile = file_get_contents($file);
if (preg_match('/\\b'.$string.'\\b/', $searchFile)) {
echo 'true';
// Find String
} else {
echo 'false';
}
How would I go about doing this?
This should work for you:
Just get your file into an array with file() and then simply preg_grep() all lines, which have the search string before the colon.
<?php
$file = "file.txt";
$search = "test";
$lines = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$matches = preg_grep("/^" . preg_quote($search, "/") . ":(.*?)$/", $lines);
$matches = array_map(function($v){
return explode(":", $v)[1];
}, $matches);
print_r($matches);
?>
output:
Array ( [0] => fOwimWPu0eSaNR8 )

Don't echo things with certain characters

I have a php program that looks at a log file and prints it to a page (code below). I don't want the user of said website to be able to look at any line containing a /. I know I could use trim to delete certain characters, but is there a way to delete the entire line? For example, I want to keep something like "Hello" and delete something like /xx.xx.xx.xx connected. All the lines I wish to delete have the same common key, /. Peoples names in said log file have <>s around them, so I must use htmlspecialcharacters
$file = file_get_contents('/path/to/log', true);
$file = htmlspecialchars($file);
echo nl2br($file);
Thanks for your help!
EDIT:
Thanks for all of the answers, currently tinkering with them!
EDIT2:
final code:
<?php
$file = file_get_contents('/path/to/log', true);
// Separate by line
$lines = explode(PHP_EOL, $file);
foreach ($lines as $line) {
if (strpos($line, '/') === false) {
$line = htmlspecialchars($line . "\n");
echo nl2br($line);
}
}
?>
Do you mean, like this?
$file = file_get_contents('/path/to/log', true);
// Separate by line
$lines = explode(PHP_EOL, $file);
foreach ($lines as $line) {
if (strpos($line, '/') === false) {
// If the line doesn't contain a "/", echo it
echo $line . PHP_EOL;
}
}
For anyone wondering, PHP_EOL is the PHP constant for "end of line" and promotes consistency between different systems (Windows, UNIX, etc.).
If you are iterating through the file line by line you can check with preg_match if the line contains /character and skip the echo if it does. If not, first split them at new line and iterate over that array.
If you don't want to split the file you can probably use preg_replace with a regexp such as (^|\n).*/.*(\n|$) and replace with empty string.
Use the str_replace function -
http://php.net/manual/en/function.str-replace.php. Alternate solution (before escaping the special characters) -
/* pattern /\/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\sconnected/ = /xx.xx.xx.xx connected */
/* pattern will be replaced with "newtext" */
$file = file_get_contents("/path/to/log", true);
$lines = explode("\n", $file);
foreach ($lines as $line)
$correctline = preg_replace( '/\/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\sconnected/', 'newtext', $line );
echo $correctline;
}
<?php
$file = file_get_contents("/path/to/log", true);
$lines = explode("\n", $file);
foreach ($lines AS $num => $line)
{
if ( strpos($line, "/") === false ) // Line doesn't contain "/"
{
echo htmlspecialchars($line) . "\n";
}
}
?>

Reading text after a certain character in php

Okay so I have a text file and inside of the text file I have these lines:
IP = 127.0.0.1
EXE = Client.exe
PORT = 8080
TITLE = Title
MAINT = False
MAINT-Message = This is the message.
what I am wanted to do is get the 'False' part on the fifth line.
I have the basic concept but I can't seem to make it work. This is what I have tried:
<?php
$file = file_get_contents('LauncherInfo.txt');
$info = explode(' = ', $file);
echo $info[5];
?>
And with this I get a result but when I echo $info[5] it gives me 'False Maint-Message' so it splits it but it only splits at the = sign. I want to be able to make it split at the where I have pressed enter to go onto the next line. Is this possible and how can I do it?
I was thinking it would work if I make it explode on line one and then do the same for the second line with a loop until it came to the end of the file? I don't know how to do this though.
Thanks.
I think you're looking for the file(), which splits a file's contents into an array of the file's lines.
Try this:
$file = file('LauncherInfo.txt');
foreach ($file as $line) {
if ($line) {
$splitLine = explode(' = ',$line);
$data[$splitLine[0]] = $splitLine[1];
}
}
echo $data['MAINT'];
Just in case you were curious, since I wasn't aware of the file() function. You could do it manually like this
<?php
$file = file_get_contents('LauncherInfo.txt');
$lines = explode("\n", $file);
$info=array();
foreach($lines as $line){
$split=explode(' = ',$line);
$info[]=$splitline[1];
}
echo $info[5];//prints False
?>

Categories