0

I'm trying to select a specific section of a specific line within a file.

For instance, I want to isolate the first line of text from a file and get the numeric value of rate without the trailing kbit text.

Sample file contents:

tc class add dev br-lan parent 1:1 classid 1:2 htb rate 100kbit ceil 100kbit
tc class add dev br-lan parent 1:1 classid 1:3 htb rate 200kbit ceil 200kbit
tc class add dev br-lan parent 1:1 classid 1:4 htb rate 300kbit ceil 300kbit

I would like to select the data between "rate " (notice the space after rate) and "kbit" based on the line number, then store it as a variable.

Expected Result:

Effectively, I would like to retrieve the results based on, for example; line 1:

100

Then store this value as a variable.

This won't work with substr, as shown here: http://php.net/manual/en/function.substr.php as the length of the integer retrieved may not always be the same length.

File path:

../etc/init.d/bandwidthlimiters/rulestest
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
Ballard
  • 869
  • 11
  • 25
  • Perhaps you could grab the number using a regex expression and `preg_match`. http://stackoverflow.com/questions/9561161/how-to-retrieve-a-part-of-a-string-based-on-an-expression-php – dragonfire Apr 16 '17 at 17:27

5 Answers5

1

Try this hope it will work fine.

<?php
ini_set('display_errors', 1);

$lines=file("path/of/file.txt");//get the content of file as an array of lines
$result=array();
foreach($lines as $lineNo=>$line)
{
    preg_match('/rate\s*\K[\d]+/', $line,$matches);
    $result[$lineNo+1]=$matches[0];
}
print_r($result);
Sahil Gulati
  • 15,028
  • 4
  • 24
  • 42
  • at the moment this prints "Array ( [1] => )" rather than the expected "100", any thoughts as to why this may be? – Ballard Apr 16 '17 at 18:00
1
<?php

$output_arr=array();
$handle = fopen("inputfile.txt", "r");
if ($handle) {

    $i=1;
    while (($line = fgets($handle)) !== false) {

    $test_string=$line;
    $test_string=str_replace(" htb rate ","@@",$test_string);
    $test_string=str_replace("kbit ceil ","@@",$test_string);

    $tmp = explode("@@", $test_string);
    array_push($output_arr,$tmp[1]);
    $i++;
   }

    fclose($handle);
} else {
    // error opening the file.
} 

echo $output_arr[2]

?>
Vijay
  • 168
  • 1
  • 2
  • 11
  • how would I implement this using lines from a file within a specified location? – Ballard Apr 16 '17 at 18:10
  • open the file as below$handle $handle = fopen("inputfile.txt", "r"); if ($handle) { while (($line = fgets($handle)) !== false) { // // place the above in this line // if need output of each line then create a array in the starting and keep on adding each output tothat array // so that in the end you will get an array which would contain all the required values } fclose($handle); } else { // error opening the file. } – Vijay Apr 16 '17 at 18:16
  • 1
    Have edited the answer for your comfort(I have not tried running the code) – Vijay Apr 16 '17 at 18:19
  • this is echoed: "Line 1 result:" with no result. Note, I have the correct file location as am using elsewhere. – Ballard Apr 16 '17 at 18:26
  • 1
    Hi Reconnected, I tried the code(plz see, I have slightly edited it further). It is working for me. I used same test case which you provided in the question – Vijay Apr 16 '17 at 18:49
  • it now prints the following: Line 1 result: 1 Line 2 result: 1 Line 3 result: 1, it does not show the expected value of 100, 200 and 300, how do I modify the code to only display a line I specify and provide the actual value rather than the number of matches? – Ballard Apr 16 '17 at 19:14
  • "how do I modify the code to only display a line I specify? " ?? Could you please elaborate it more with exact requirement. Do you want to specify a limit on number of lines you reading from file or want to ignore few lines? Please explain in detail – Vijay Apr 16 '17 at 19:18
  • I want to grab the "100" from the first line, store it as a variable and echo it, as shown in the "expected result" of the question – Ballard Apr 16 '17 at 19:19
  • 1
    Done. Please check the answer now. Hope that helps else sorry for wasting your time – Vijay Apr 16 '17 at 19:26
  • Just kept a break statement in the loop so that it comes out of the loop after reading the first line. – Vijay Apr 16 '17 at 19:27
  • This works as I would like! Thanks! However, it does not allow me to retrieve the result of any other line in the file, I.e: line 2 or 3, any idea? – Ballard Apr 16 '17 at 19:35
  • I assumed it was a case of modifying "$required_output=$tmp[1]; to "$required_output=$tmp[2];", however this does not work – Ballard Apr 16 '17 at 19:36
  • 1
    I have done this for you now... just place right index on $output_arr[2] variable as per your requirement and I hope this is what you were looking for – Vijay Apr 16 '17 at 19:45
1

This task requires two basic subtasks:

  1. Accessing a specified line in a file and
  2. Extracting a substring from a string.

For subtask #1, there is good advice at PHP: Read Specific Line From File which explains that a developer can choose succinct syntax with file() to read relatively small files or use an SplFileObject with seek() to efficiently target one line.

  1. With file():

    $lineNumber = 1;
    $line = file('your/path/to/file.txt')[$lineNumber - 1];
    
  2. With SplFileObject:

    $lineNumber = 1;
    $spl = new SplFileObject('your/path/to/file.txt'); // temporarily locks file
    $line = $spl->seek($lineNumber - 1)->current();
    $spl = null; // unlock file
    

For subtask #2, targetting the desired substring can be done a myriad of ways depending on the sought characters, preceeding characters, delimiters in the text, etc. I'll list a couple basic techniques.

  1. Explode on delimiting spaces and cast as an integer to trim kbit characters by consequence: Demo

    $rate = (int) explode(' ', $line)[11];
    
  2. Regular expression: Demo

    $rate = preg_replace('/.* rate (\d+).*/', '$1', $line);
    

No matter which combination of techniques you choose, there is certainly no need to implement hacky string replacements to introduce placeholders before extracting the desired text.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
0

This should solve the issue:

<?php
$lines = file("../etc/init.d/bandwidthlimiters/rulestest");
$results = array();
foreach($lines as $num=>$line) {
    preg_match("/([0-9]+)\s*kbit/i", $str, $out);
    if(isset($out[1])) $results[$num] = $out[1];
}

Now,

$results = array with results where index is the line number corresponding each result

Hossam
  • 1,126
  • 8
  • 19
0

Verifies there's a ("rate ") string before and ("kbit") string ahead, not consuming either of them:

/(?<=rate\s)\d+(?=kbit)/

Code:

<?php
$lines=file("file.txt");
$result=array();
foreach($lines as $oneline)
{
    preg_match('/(?<=rate\s)\d+(?=kbit)/', $oneline, $matches);
    $result[]=$matches[0];
}
?>

file.txt:

tc class add dev br-lan parent 1:1 classid 1:2 htb rate 100kbit ceil 100kbit
tc class add dev br-lan parent 1:1 classid 1:3 htb rate 200kbit ceil 200kbit
tc class add dev br-lan parent 1:1 classid 1:4 htb rate 300kbit ceil 300kbit

$result:

Array
(
    [0] => 100
    [1] => 200
    [2] => 300
)
Arbels
  • 201
  • 2
  • 6