I need to find a specic line of text, from a text-file,
and then copy it to a new text-file:
1: I have a text file with several lines of text, eg:
JOHN
MIKE
BEN
*BJAMES
PETE
2: So, I read that text-files contents into an array,
with each line of text, placed into a seperate element of the array.
3: Then I tested each element of the array,
to find the line that starts with, say: *B ie:
if ( preg_match( "/^\*(B)/",$contents[$a] ) )
Which works ok...
4: Then I copy (WRITE) that line of text, to a new text-file.
Q: So how can I remove the '*B' from that line of text,
BEFORE I WRITE it to the new text-file ?
If you already use preg_match, you can modify your regex to get what you want in another variable.
if (preg_match('/^\*B(.*)$/', $contens[$a], $matches)
{
fwrite($targetPointer, $matches[1]);
}
After using preg_matchthe variable $matches holds the single matches of subparts of the regex enclosed in brackets. So the relevant part of your line ist matched by (.*) and saved into $matches[1].
This approach writes the lines as the file is read, which is more memory efficient:
$sourceFile = new SplFileObject('source.txt');
$destinationFile = new SplFileObject('destination.txt', 'w+');
foreach (new RegexIterator($sourceFile, '/^\*B.*/') as $filteredLine) {
$destinationFile->fwrite(
substr_replace($filteredLine, '', 0, 2)
);
}
demo
With substr or preg_replace.
Have a try with:
preg_replace('/^\*B/', '', $content[$a], -1, $count);
if ($count) {
fwrite($file, $content[$a]);
}
Related
This question already has an answer here:
How to find a whole word in a string in PHP without accidental matches?
(1 answer)
Closed 2 years ago.
This might look like a duplicate but Its a different issue. I'll almost copy/paste another Question but I'm asking for a different issue. Also since that thread owner asked it very well and understandable I will describe it like he did.
I have a normal text files with each line having data in the following format.
Username | Age | Street
Now what I wanted to do was to search for the Username in the file and when found It will print the whole line. The question below does this perfectly with one main problem:
PHP to search within txt file and echo the whole line
Issue: If you have the name "Tobias" and search for "Tobi" it will find it and disply "Tobias" but I only want to search a whole word that your using as the search string. If I want to search for "Tobi" it should only find "Tobi" and not "Tobias" or every other string containing the word "Tobi".
It works using this solution: https://stackoverflow.com/a/4366744/14071499
But that also has the issue that using the solution above would only print the string that I am searching for and doesn't print the whole line.
So how am I able to search for a word and printing the whole line afterwards without also finding other string that aren't only the word but containing it?
The Code I have so far:
<?php
$file = 'ids.txt';
$searchfor = $_POST['search'];
// 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 = "/\b{$pattern}.*\$/m";
// search, and store all matching occurences in $matches
if(preg_match_all($pattern, $contents, $matches)){
echo "Found matches:\n";
echo implode("\n", $matches[0]);
}
else{
echo "No matches found";
}
?>
This answer doesn't take into account fields in your source data, since at the moment you're just bulk-matching the raw text and interested in getting full lines. There is a much simpler way to accomplish this, ie. by using file that loads each line into an array member, and the application of preg_grep that filters an array with a regular expression. Implemented as follows:
$lines = file('ids.txt', FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES); // lines as array
$search = preg_quote($_POST['search'], '~');
$matches = preg_grep('~\b' . $search . '\b~', $lines);
foreach($matches as $line => $match) {
echo "Line {$line}: {$match}\n";
}
In related notes, to match only complete words, instead of substrings, you need to have word boundaries \b on both sides of the pattern. The loop above outputs both the match and the line number (0-indexed), since array index keys are saved when using preg_grep.
<?php
$file = "ids.txt";
$search = $_POST["search"];
header("Content-Type: text/plain");
$contents = file_get_contents($file);
$lines = explode("\n", $contents);
foreach ($lines as $line) {
if (preg_match("/\b${search}\b/", $line, $matches)) {
echo $line;
}
}
I have a text file with data that looks like this:
#dacdcadcasvsa
#svsdvsd
#
#sfcnakjncfkajnc
I want to keep this line
and this one
How can I remove all lines containing # and echo out the lines that don't so it looks like:
I want to keep this line
and this one
All I know is that I have to get_file_contents($filename). Would I have to put it in an array?
Any tips and guidance would be appreciated.
Using file() and foreach()
$lines = file("a.txt");
foreach ( $lines as $line ) {
if ( $line[0] != '#' ){
echo $line;
}
}
Just update the name of the file.
You can replace all the comment lines with empty strings before you output.
<div style="white-space: pre-line;">
<?= preg_replace('/^#.*\n/m', '', file_get_contents($filename)) ?>
</div>
You're thinking along the right lines; although the PHP method (function) you need is actually file_get_contents(), not get_file_contents() (as per your question).
Let's break it down:
We need a way of separating out our data into sortable chunks. As you stated, the best way to do this is using an array.
We could do this, using the hash symbol (#) as a delimiter - but this
would mean the last chunk of text is a mixture of text we want to
remove, and text we want to keep. Instead, we'll be using line
breaks as our delimiter.
Once the data has been separated, we can work on removing those lines that begin with a hash symbol.
Our code will look something like this:
<?php
// Get the file contents
$fileContents = file_get_contents('my_file.txt'); // This could be any file extension
// Split the file by new lines
$contentsArr = preg_split('/\r\n|\r|\n/', $fileContents);
// Function for removing items from an array - https://stackoverflow.com/questions/9993168/remove-item-from-array-if-item-value-contains-searched-string-character?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa
function myFilter($string) {
return strpos($string, '?') === false;
}
// Remove comment items from array
$newFileContents = array_filter($fileContents, 'myFilter');
// Concatenate and echo out the result
echo implode(",\n",$newFileContents);
An alternate because I was bored:
foreach(preg_grep('/^#/', file($filename), PREG_GREP_INVERT) as $line) {
echo $line;
}
Read file lines into an array
Get all lines NOT starting with ^ the # character
Loop those lines
This should be a simple task, but searching for it all day I still can't figure out what I'm missing
I'm trying to open a file using PHP's glob() that begins with a specific number
Example filenames in a directory:
1.txt
123.txt
10 some text.txt
100 Some Other Text.txt
The filenames always begin with a unique number (which is what i need to use to find the right file) and are optionally followed by a space and some text and finally the .txt extension
My problem is that no matter what I do, if i try to match the number 1 in the example folder above it will match every file that begins with 1, but I need to open only the file that starts with exactly 1, no matter what follows it, whether it be a space and text or just .txt
Some example regex that does not succeed at the task:
filepath/($number)*.txt
filepath/([($number)])( |*.?)*.txt
filepath/($number)( |*.?)*.txt
I'm sure there's a very simple solution to this... If possible I'd like to avoid loading every single file into a PHP array and using PHP to check every item for the one that begins with only the exact number, when surely regex can do it in a single action
A bonus would be if you also know how to turn the optional text between the number and the extension into a variable, but that is entirely optional as it's my next task after I figure this one out
The Regex you want to use is: ^99(\D+\.txt)$
$re = "/^99(\D+\.txt)$/";
preg_match($re, $str, $matches);
This will match:
99.txt
99files.txt
but not:
199.txt
999.txt
99
99.txt.xml
99filesoftxt.dat
The ( ) around the \D+.txt will create a capturing group which will contain your file name.
I believe this is what you want OP:
$regex = '/' . $number . '[^0-9][\S\s]+/';
This matches the number, then any character that isn't a number, then any other characters. If the number is 1, this would match:
1.txt
1abc.txt
1 abc.txt
1_abc.txt
1qrx.txt
But it would not match:
1
12.txt
2.txt
11.txt
1.
Here you go:
<?php
function findFileWithNumericPrefix($filepath, $prefix)
{
if (($dir = opendir($filepath)) === false) {
return false;
}
while (($filename = readdir($dir)) !== false) {
if (preg_match("/^$prefix\D/", $filename) === 1) {
closedir($dir);
return $filename;
}
}
closedir($dir);
return false;
}
$file = findFileWithNumericPrefix('/base/file/path', 1);
if ($file !== false) {
echo "Found file: $file";
}
?>
With your example directory listing, the result is:
Found file: 1.txt
You can use a regex like this:
^10\D.*txt$
^--- use the number you want
Working demo
For intance:
$re = "/^10\\D.*txt$/m";
$str = "1.txt\n123.txt\n10 some text2.txt\n100 Some Other2 Text.txt";
preg_match_all($re, $str, $matches);
// will match only 10 some text.txt
Example (file=xref.tex):
This is a example string and first line with <xref>id1</xref>then,<xref>id2</xref>and with no line breaks<xref>id3</xref>.
This is a second line which has <xref>id4</xref>
Example (file=id):
id1 eqvalue1
id2 eqvalue2
id3 eqvalue3
id4 eqvalue4
Requirement: Every unique id has a equivalent value. I need to replace that equivalent value in the place of id in each occurrences in "xref.tex" file.
Tried so far:
$xref=file("xref.tex");
$idfile=file("id");
for($y=0;$y<count($xref);$y++){
for($z=0;$z<count($idfile);$z++){
$idvalue=explode(" ",$idfile[$z])//exploding based on space charac
$id1=$idvalue[0]; //this is equivalent value of unique id
$id2=$idvalue[1]; // this is unique id
preg_match( '/<xref>(.*?)<\/xref/', $xref[$y], $match );
//getting the content between "<xref>"and "</xref>"
if($match[1]===$id2{
$xref[$y]=str_replace($match[1],$id1,$xref[$y]);}
//here first occurrence of id is replaced. how to replace
//second occurrence of id in a line as
//preg_match( '/<xref>(.*?)<\/xref/', $xref[$y], $match )
//this regex focusing on first occurrence only every time.
//???? prob here is how can i do this logic in all the occurrences
//in each line
}
}
}
Expected output:
This is a example string and first line with <xref>eqvalue1</xref>then,<xref>eqvalue2</xref>and with no line breaks<xref>eqvalue3</xref>.
This is a second line which has <xref>eqvalue4</xref>
Here is what I understand. The contents of the file xref.tex is as follows
<xref>id1</xref><xref>id2</xref><xref>id3</xref><xref>id4</xref> //line 1
<xref>id2</xref><xref>id3</xref> //line 2
<xref>id4</xref> //line 3
... and so on
First of all, you have to fix the regex. You're missing > at the end of it. It should be
/<xref>(.*?)<\/xref>/
Then you need to use preg_match_all instead of preg_match as suggested.
I've modified the code a little bit. This should also work if you have same id repeating in a single line.
$xref=file("xref.tex");
$idfile=file("id");
for($y=0;$y<count($xref);$y++)
{
preg_match_all( '/<xref>(.*?)<\/xref/', $xref[$y], $match ); //get all matches and store them in *match*
for($z=0;$z<count($idfile);$z++)
{
$idvalue=explode(" ",$idfile[$z]);
$id1=$idvalue[0];
$id2=$idvalue[1];
//Below, we're replacing all the matches in line with corresponding value. Edit: Maybe not the best way, but it will give you an idea.
foreach($match[0] as $matchItem)
$xref[$y]=str_replace($matchItem,$id1,$xref[$y]);
}
}
EDIT
You might want to check preg_replace. I think that would be a better solution.
Read the file "id" as space separated csv to an array and then use that array with preg_replace on the other file as string using file_get_contents.
Try this:
$re = "/(<xref>[^\\d]+)(\\d)(<\\/xref)/m";
$str = "This is a example string and first line with <xref>id1</xref>then,<xref>id2</xref>and with no line breaks<xref>id3</xref>. This is a second line which has <xref>id4</xref>";
$subst = "$1eqvalue$2$3";
$result = preg_replace($re, $subst, $str);
Live demo
I would like to put a text instead of the string VERSION=20101203, my problem is only the first field of preg_replace, I am new to regular expresions. I don't know exactly how to tell preg_replace to see that I need to change the string VERSION=20101203 for other text.
So the string has the format:VERSION=YEARMONTHDAY
I was trying with:
$new_content = preg_replace('/^VERSION\=[0-9]{8}/', $replacement, $content);
Where:
$replacement is the new string I want to have
$content is the content of a file that it doesn't matter here
I beleive it's not too difficult. Any questions you may have with this issue please ask me and I will answer quickly
Thank you very much in advance
^ is anchoring the regular expression to only the beginning of the line. I assume that's part of the problem.
$new_content = preg_replace('/VERSION\=[0-9]{8}/', $replacement, $content);
In addition, you will want to ensure that $replacement contains the full string for replacing the string matched by VERSION\=[0-9]{8}.
Try this code (without ^ at the start of regular expression):
$content='foo VERSION=20101203 foo bar';
var_dump( preg_replace('/VERSION=[0-9]{8}/', 'replacement', $content));
OUTPUT
string(23) "foo replacement foo bar"
Well it was solved with Jason McCreary's suggestion. It worked just without ^ and the rest of the code is the same as I had it before.
I was trying to change the string VERSION=YEARMONTHDAY (which is in one of the lines of the $ks file). I mean that the file contains in one of its lines this:
VERSION=20101203 (or any other date, but everytime with the same format)
That string is going to be changed by a new one that matches to the last modification of the file stored in the variable $ks. ($ks is the name of the file)
$last_modification = filemtime($ks);
$last_modification = date("Ymd", $last_modification);
// $last_modification (for instance suppose it is VERSION=20110622)
$last_modification="VERSION=" . $last_modification;
// Open the file in order to change the string
$file = $ks;
$fh = fopen($ks, 'r+');
$content = fread($fh, filesize($ks));
$new_content = preg_replace('/VERSION\=[0-9]{8}/', $last_modification, $content);
fclose($fh);
// Open the file in order to write inside it
$fh = fopen($ks, 'r+');
fwrite($fh, $new_content);
fclose($fh);
So the final result is going to be: the file named $ks will have a line with VERSION=20110622 instead of the VERSION=20101203 (or any other older date) string.
The code is working fine this way for me. Thank you all again, I don't know if I have to close this issue, as it is solved
PD: Sorry for my english