grep with -f like in PHP - php

Is there such a function in PHP that does grep -f filename in unix/linux systems.
If there is none, what PHP functions/tools would help in creating a customised method/function for this. Thanks!

Actually IMHO, I'd say it's the following:
$result = preg_grep($pattern, file($path));
See preg_grep­Docs and file­Docs.
If you need to do that (recursively) over a set of files, there is also glob and foreach or the (Recursive)DirectoryIterator or the GlobIterator­Docs and not to forget the RegexIterator­Docs.
Example with SplFileObject and RegexIterator:
$stream = new SplFileObject($file);
$grepped = new RegexIterator($stream, $pattern);
foreach ($grepped as $line) {
echo $line;
}
Output (all lines of $file containing $pattern):
$grepped = new RegexIterator($stream, $pattern);
foreach ($grepped as $line) {
echo $line;
}
Demo: https://eval.in/208699

You can combine the file_get_contens() function to open a file and the preg_match_all() function to capture contents using a regex.
$file = file_get_contents ('path/to/file.ext');
preg_match_all ('regex_pattern_here', $file, $matches);
print_r ($matches);

Related

How to get preg_replace() to delete text between two tags?

I'm trying to make a function in PHP that can delete code within two tags from all .js file within one folder and all its subfolders. So far everything works except preg_replace(). This is my code:
<?php
deleteRealtimeTester('test');
function deleteRealtimeTester($folder_path)
{
foreach (glob($folder_path . '/*.js') as $file)
{
$string = file_get_contents($file);
$string = preg_replace('#//RealtimeTesterStart(.*?)//RealtimeTesterEnd#', 'test2', $string);
$file_open = fopen($file, 'wb');
fwrite($file_open, $string);
fclose($file_open);
}
$subfolders = array_filter(glob($folder_path . '/*'), 'is_dir');
if (sizeof($subfolders) > 0)
{
for ($i = 0; $i < sizeof($subfolders); $i++)
{
echo $subfolders[$i];
deleteRealtimeTester($subfolders[$i]);
}
}
else
{
return;
}
}
?>
As mentioned I want to delete everything inside these tags and the tags themselve:
//RealtimeTesterStart
//RealtimeTesterEnd
It is important that the tags contains the forward slashes and also that if a file contains multiple of these tags, only code from //RealtimeTesterStart to //RealtimeTesterEnd is deleted and not from //RealtimeTesterEnd to //RealtimeTesterStart.
I hope that someone can help me.
You could also change your regex to use the [\s\S] character set which can be used to match any character, including line breaks.
So have the following
preg_replace('#\/\/RealtimeTesterStart[\s\S]+\/\/RealtimeTesterEnd#', '', $string);
This would remove the contents of //RealtimeTesterStart to //RealtimeTesterEnd and the tags themselves.
I'm assuming that //RealtimeTesterStart, //RealtimeTesterEnd and the code in between are on different lines? In PCRE . does NOT match newlines. You need to use the s modifier ( and you don't need the () unless you need the captured text for the replacement):
#//RealtimeTesterStart.*?//RealtimeTesterEnd#s
Also, look at GLOB_ONLYDIR for glob instead of array_filter. Also, also, maybe file_put_contents instead of fopen etc.
Maybe something like:
foreach (glob($folder_path . '/*.js') as $file) {
$string = file_get_contents($file);
$string = preg_replace('#//RealtimeTesterStart.*?//RealtimeTesterEnd#s', 'test2', $string);
file_put_contents($file, $string);
}
foreach(glob($folder_path . '/*', GLOB_ONLYDIR) as $subfolder) {
deleteRealtimeTester($subfolder);
}

for loop looping to tlast item in text file

I been working trying everything to get this to work any help would be greatly apreciated.
i tried many couple of ways to get this work but i either get this error that the domain ame parameter is empty or I get the last domain in the txt file.
the txt file is just one domain per line.
$address="file.txt";
$shit=fopen($address,"r");
$contents2= fread($shit,filesize($address));
//also tried $domainlist=explode("\n\r",$contents2);
$domainlist=explode("\n",$contents2);
for($i=0 ; $i<=count($domainlist); ++$i){
$domainlist[$i]=$domain;
$contents = file_get_contents("http://www.whoisxmlapi.com/whoisserver/WhoisService?
domainName=$domain&username=$username&password=$password&outputFormat=JSON");
$results=json_decode($contents);
print_r($results);
unset($domain);
};
?>
Easier:
$lines = file("file.txt", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach($lines as $domain) {
$contents = file_get_contents("http://www.whoisxmlapi.com/whoisserver /WhoisService?domainName=$domain&username=$username&password=$password&outputFormat=JSON");
$results = json_decode($contents);
print_r($results);
}
You may want to trim($domain) or make sure it's valid or other checks before doing file_get_contents().
$file = fopen("file.txt", "r");
while(!feof($file)){
$line = fgets($file);
$last_line = $line;
}
fclose($file);
echo $last_line;
A few ways to do this...
$file = file("file.txt");
foreach($file as $line) {
// do something with the $line
}
I prefer this method unless you're unsure of the file size. If unsure, you may want to consider using fopen.

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
?>

PHP file to open and modify other php (With find and replace via regex?)

I want to do the following
I want to create .php file (executed via cronjobs) that will paste this code $files[] = 'example.php';
to other php file (paste.php) but it has to find the lastest $files[] line like regex $files[] = '(AnythingHere)'; and after this line to paste the new line. It can have random number of pages so I have no way of knowing.
<?php
if (!isset($php_file)) {
$files[] = 'page1.php';
$files[] = 'page2.php';
$files[] = 'page3.php';
$files[] = 'page4.php';
$file = $files[ rand(0,count($files)) ];
I hope you guys understand what I want; can anyone help me out with this one?
if you have ONLY $file[] = '...' in paste.php, you can simply append to the file:
$line = '$file[] = "pageX.php";' . PHP_EOL;
file_put_contents('paste.php', $line, FILE_APPEND);
of you want the last "page[]" enty.
$yourNewLine = '$file[] = "pageX.php";'; // this is an example. put your "line" prm here
$filename = 'paste.php';
$lines = file($filename);
$lines = array_reverse($lines)
$found = false;
$i = 0;
while ( ! $found )
{
if ( strpos($lines[$i], '$files[] = ' === 0) )
{
$found = true;
array_splice($lines, $i, 0, $yourNewLine.PHP_EOL);
}
$i++;
}
$lines = array_reverse($lines);
file_put_contents($filename, $lines);
Instead of doing it this way, how about instead setting your files array in a script and then include it at the top. This way you can reference the array directly and still only have to edit the file listing in only one place.
Quick and dirty first-fit solution:
Open the file
Read each line until you find one matching your regex for $files[] = ...
Read more lines until you find one that doesn't match the regex
Write each line read in 2 and 3 to the output file
Insert your new line into the output
Write the rest of the input to the output
This may not be the best way to approach the problem, drawbacks being that you have to read each line in and compare it with your regex until you find your insertion point. You'll also probably have a temporary file for output which you'll then rename to the original filename.
You'll have 2 while loops:
while (line does not match): read next line
and then
while (line does match): read next line
Someone who knows PHP better than I do might be able to come up with something a bit cleaner, but if you're just looking for something quick to get the job done, this ought to work.
Having this code:
$filesArray = array('page1.php','page2.php','page3.php','page4.php','page5.php',);
then getting the php file with $data = file("path/to/editable_file.php");
foreach($data as $line)
{
if(preg_replace("/\$filesArray\s=\sarray\([\w'.,]+()\);/", "'".$newfilename."',", $line, $match))
{
file_put_contents(implode("\r\n", $data));
break;
}
}

Categories