php stripping a particular result from an output - php

I am using php to grab a shell output that lists all the meetme channels for me. I just want to grab the Conf Num that has 0001 from the bottom up. In my example below, I would like to assign variable: $confnum="32";
Here is my code so far:
$output = shell_exec("asterisk -rx 'meetme list'");
echo $output;
Please help me take the results from $output.
Here's what you'll get when executing the meet.php file
[root#C1033-TF agi-bin]# php meet.php
Conf Num Parties Marked Activity Creation Locked
67 0001 N/A 00:00:16 Dynamic No
28 0001 N/A 00:00:19 Dynamic No
65 0001 N/A 00:01:14 Dynamic No
42 0001 N/A 00:01:18 Dynamic No
32 0001 N/A 00:04:18 Dynamic No
* Total number of MeetMe users: 5
Please keep in mind that sometime there will be more than just 0001 Parties in the Conf Num. In the example above, I just want to grab the line:
32 0001 N/A 00:04:18 Dynamic No
This is the last line that has 0001 therefore assign $confnum="32"; to it.
Any kind of help I can get on this is greatly appreciated.

You can use exec instead of shell_exec and iterate through the output lines:
<?php
$output = array();
exec("asterisk -rx 'meetme list'", $output);
foreach ($output as $line) {
if (preg_match('/^32\s/', $line)) { //Check line starts with 32
echo $line;
}
}
Edit:
<?php
$output = array();
exec("asterisk -rx 'meetme list'", $output);
$lines = sizeof($output);
for ($i = $lines -1; $i >=0 ; $i--) {
if (preg_match('/^(\d+)\s+0001\s/', $output[$i], $matches)) { //Check line contains 0001
$firstNumber = $matches[1];
echo $firstNumber;
break;
}
}

Okay, assuming Linux, you can do this purely in shell:
filter last line: grep -v 'Total number of MeetMe isers'
filter first line: grep -v 'Conf Num'
and print only one Conf Num: awk 'BEGIN{ result=""; } {if( $2 == "0001"){result=$1;}} END {print result;}'
So the whole code:
$output = shell_exec("asterisk -rx 'meetme list' | grep -v 'Total number of MeetMe isers' | grep -v 'Conf Num' | awk 'BEGIN{ result=\"\"; } {if( \$2 == \"0001\"){result=$1;}} END {print result;}'");
// $output should contain your data :)
Or use preg_match_all():
$output = shell_exec("asterisk -rx 'meetme list'");
$matches = array();
$result = null;
preg_match_all('~^\s*(\\d+)\\s+0001~', $output, $matches, PREG_SET_ORDER);
foreach( $matches as $match ){
$result = $match[1];
}
In reaction to comment:
You should study regular expression syntax and meaning of \d and +. \d+ will match 0, 01 or 00000000000000000000000000000000 :).

Related

Split string at column positions

I am using
ps -l -u user
to get the running processes of a given user.
Now, when I want to split the information into arrays in PHP I am in trouble because ps outputs the data for humans to read without fixed delimiters. So you can't split with space or tab as regex.
So far I can only detect the columns by character positions.
Is there any way in php to split a string into an array at certain positions? Something like:
$array=split_columns($string, $positions=array(1, 10, 14))
to cut a string into pieces at positions 1, 10 and 14?
I decided to try a regex approach with dynamic pattern building. Not sure it is the best way, but you can give it a try:
function split_columns ($string, $indices) {
$pat = "";
foreach ($indices as $key => $id) {
if ($key==0) {
$pat .= "(.{" . $id . "})";
} else if ($key<count($indices)) {
$pat .= "(.{" . ($id-$indices[$key-1]) . "})";
}
}
$pats = '~^'.$pat.'(.*)$~m';
preg_match_all($pats, $string, $arr);
return array_slice($arr, 1);
}
$string = "11234567891234567\n11234567891234567"; // 1: '1', 2: '123456789', 3: '1234', 4: '567'
print_r (split_columns($string, $positions=array(1, 10, 14)));
See the PHP demo
The point is:
Build the pattern dynamically, by checkign the indices, subtracting the previous index value from each subsequent one, and append the (.*)$ at the end to match the rest of the line.
The m modifier is necessary for ^ to match the start of the line and $ the end of the line.
The array_slice($arr, 1); will remove the full match from the resulting array.
A sample regex (meeting OP requirements)) will look like ^(.{1})(.{9})(.{4})(.*)$
I modified Wiktor's solution as I don't need that many information.
function split_columns ($string, $indices) {
$pat = "";
foreach ($indices as $key => $id) {
if ($key==0) {
$pat .= "(.{" . $id . "})";
} else if ($key<count($indices)) {
$pat .= "(.{" . ($id-$indices[$key-1]) . "})";
}
}
$pats = '~^'.$pat.'(.*)$~m';
preg_match_all($pats, $string, $arr, PREG_SET_ORDER);
$arr=$arr[0];
return array_slice($arr, 1);
}
In PHP preg_split will help you here. You can split by a number of whitespaces e.g.:
<?
$text = '501 309 1 4004 0 4 0 2480080 10092 - S 0 ?? 0:36.77 /usr/sbin/cfpref
501 310 1 40004004 0 37 0 2498132 33588 - S 0 ?? 0:23.86 /usr/libexec/Use
501 312 1 4004 0 37 0 2471032 8008 - S 0 ?? 19:06.48 /usr/sbin/distno';
$split = preg_split ( '/\s+/', $text);
print_r($split);
If you know the number of columns you can then go through the array and take that number of columns as one row.

ValueError: need more than 0 values to unpack error in Python

Today I tried to execute the following command in Linux, I want to test the Streaming interface in hadoop,
cat test.txt|php wc_mapper.php|python Reducer.py
an error happened:
"Traceback (most recent call last):
File "Reducer.py", line 7, in <module>
word,count = line.split()
ValueError: need more than 0 values to unpack
"
the content of test.txt is as follows:
hello world
hello world
hello world
the content of wc_mapper.php which is written by PHP is
#!/usr/bin/php
<?php
error_reporting(E_ALL ^ E_NOTICE);
$word2count = array();
while (($line = fgets(STDIN)) !== false) {
$line = trim($line);
$words = preg_split('/\W/', $line, 0, PREG_SPLIT_NO_EMPTY);
foreach ($words as $word) {
echo $word, chr(9), "1", PHP_EOL;
}
}
?>
and the content of Reducer.py which is written by Python is
#!/usr/bin/python
from operator import itemgetter
import sys
word2count = {}
for line in sys.stdin:
line = line.strip()
word,count = line.split()
try:
count = int(count)
word2count[word] = word2count.get(word, 0) + count
except ValueError:
pass
sorted_word2count = sorted(word2count.items(), key=itemgetter(0))
for word,count in sorted_word2count:
print '%s\t%s'%(word,count)
who knows the reason of the error, how to fix this issue?
when I execute the first part command
cat test.txt|php wc_mapper.php|sort
, I got the following output:
hello 1
hello 1
hello 1
world 1
world 1
world 1
the first line is null, but it occupy one line.
Provide delimiter in split() function
try:
word,count = line.split(" ")
except:
print("Error")
I have put single space as delimiter. you can change accordingly.

List highest number inside all text files (multiple text files in directory)

I have a directory with multiple text files.
For example:
name1.txt
name2.txt
name3.txt
etc.. etc..
Each text file holds 1 line, on that line is a number i.e "10"
I was wondering if it'd be possible to somehow echo back the text file names of say the top 10 highest numbers of all the text files.
I was wondering if this could be done live via PHP or updated periodically via a bash script / cron
Thanks!
Not the most efficient idea but assuming you can't use a DB (otherwise you probably would):
<?php
$files = scandir('path/to/files/directory');
$rows = Array();
foreach($files as $file){
array_push($rows,file_get_contents('path/to/files/directory/'.$file);
}
arsort($rows);
$i = 0;
foreach($rows as $key => $row){
if($i <= 10){
echo 'On '.$files[$key].' the number is'.$row;
}
}
?>
grep . name*.txt | sort -nr -k2 | head -n 3
Output (e.g.):
name4.txt:1
name3.txt:123
name2.txt:444
With bash.
First, create some files:
for n in $(seq 20); do echo $RANDOM > name${n}.txt; done
Now, top 5:
$ for f in *; do printf "%s\t%d\n" "$f" $(<$f); done | sort -k2nr | head -n 5
name16.txt 30283
name12.txt 29976
name8.txt 28948
name4.txt 28256
name6.txt 28148
Just the filenames
$ for f in *; do printf "%s\t%d\n" "$f" $(<$f); done | sort -k2nr | head -n 5 | cut -f1
name16.txt
name12.txt
name8.txt
name4.txt
name6.txt

Execute background system command and capture output in a array using PHP

I'm trying to ping a bunch of IPs using PHP/HTML.
<?php
$ip=array("192.10.1.1","192.10.1.2","192.10.1.3","192.10.1.4","192.10.1.5")
$list=count($ip);
$instruction = "";
for ($x=0; $x<$list; $x++)
{
if ($x > 0)
{
$send2_bg =" & ";
}
else
{
$send2_bg = "";
}
$instruction = $instruction.$send2_bg."ping -c 2 -w 1 ". $ip[$x]." | grep -i received | awk '{print $4}'" ;
}
echo $instruction;
$result =exec($instruction);
?>
Expected output array
1 1 0 0 2
But I'm failing to get the output, The instruction is constructed perfectly but after exec(), the output is not as I expect.
exec() just returns the last line of the output
shell_exec() returns all output
Try capturing the output like this:
exec($command, $host, $output);
print_r($output);
The problem is that you are echoing the instruction var see that link - PHP manual
Please reffer to the parameter output and echo that one instead the instruction var.

how to read in file in lines of three?

So, say you have a php post script that appends whatever you pass to it to a text file as a new line
Let say the file is called file.txt and looks like this:
11:45 Am
12:49 PM
Went to Lunch
3:25 PM
I wanna know, how can I write a php script that treats information as pairs of 3.
so in a for loop it would display
line1 | line2 | line3
line4
Notice that there is nothing past line4, so it stopped.
You can use (demo)
$chunksOfThree = array_chunk(file('/path/to/file', FILE_IGNORE_NEW_LINES), 3);
foreach ($chunksOfThree as $chunk) {
echo implode(' | ', $chunk), PHP_EOL;
}
This will output the desired
11:45 Am | 12:49 PM | Went to Lunch
3:25 PM
See the Manual entries for
file — Reads entire file into an array and
array_chunk — Split an array into chunks
implode — Join array elements with a string
fgets reads an entire line from the file. It is slower than something like fread but does what you want.
You can also use the file function to read the whole file into an array. Each element in the array corresponds to a line in the file.
If the number of lines read is not a multiple of 3, just ignore the last 1 or 2 lines.
fgets returns false if there is no more data so you can check that to determine if one of the triplet entries is incomplete.
while(!feof($fp)) {
$line1 = fgets($fp);
$line2 = fgets($fp);
$line3 = fgets($fp);
if ($line2 === false) {
echo "$line1";
} else if ($line3 == false) {
echo "$line1 | $line2";
} else {
echo "$line1 | $line2 | $line3\n";
}
You can use this code for this
<?php
$filename = "test.txt";
$fp = fopen( $filename, "r" ) or die("Couldn't open $filename");
$i=0;
while ( ! feof( $fp ) ) {
$line = fgets( $fp, 1024 );
if($i==2)
{
print "$line";
$i=0;
print "<br>";
}
else
{
print "$line | ";
$i++;
}
}
?>
Output :
11:45 Am | 12:49 PM | Went to Lunch
3:25 PM |

Categories