I am working on scraping and then parsing an HTML string to get the two URL parameters inside the href. After scraping the element I need, $description, the full string ready for parsing is:
<a target="_blank" href="CoverSheet.aspx?ItemID=18833&MeetingID=773">Description</a><br>
Below I use the explode parameter to split the $description variable string based on the = delimiter. I then further explode based on the double quote delimiter.
Problem I need to solve: I want to only print the numbers for MeetingID parameter before the double quote, "773".
<?php
echo "Description is: " . htmlentities($description); // prints the string referenced above
$htarray = explode('=', $description); // explode the $description string which includes the link. ... then, find out where the MeetingID is located
echo $htarray[4] . "<br>"; // this will print the string which includes the meeting ID: "773">Description</a><br>"
$meetingID = $htarray[4];
echo "Meeting ID is " . substr($meetingID,0,3);
?>
The above echo statement using substr works to print the meeting ID, 773.
However, I want to make this bulletproof in the event MeetingID parameter exceeds 999, then we would need 4 characters. So that's why I want to delimit it by the double quotes, so it prints all numbers before the double quotes.
I try below to isolate all of the amount before the double quotes... but it isn't seeming to work correctly yet.
<?php
$htarray = explode('"', $meetingID); // split the $meetingID string based on the " delimiter
echo "Meeting ID0 is " . $meetingID[0] ; // this prints just the first number, 7
echo "Meeting ID1 is " . $meetingID[1] ; // this prints just the second number, 7
echo "Meeting ID2 is " . $meetingID[2] ; // this prints just the third number, 3
?>
Question, why is the array $meetingID[0] not printing the THREE numbers before the delimiter, ", but rather just printing a single number? If the explode function works properly, shouldn't it be splitting the string referenced above based on the double quotes, into just two elements? The string is
"773">Description</a><br>"
So I can't understand why when echoing after the explode with double quote delimiter, it's only printing one number at a time..
The reason you're getting the wrong response is because you're using the wrong variable.
$htarray = explode('"', $meetingID);
echo "Meeting ID0 is " . $meetingID[0] ; // this prints just the first number, 7
echo "Meeting ID1 is " . $meetingID[1] ; // this prints just the second number, 7
echo "Meeting ID2 is " . $meetingID[2] ; // this prints just the third number, 3
echo "Meeting ID is " . $htarray[0] ; // this prints 773
There's an easier way to do this though, using regular expressions:
$description = '<a target="_blank" href="CoverSheet.aspx?ItemID=18833&MeetingID=773">Description</a><br>';
$meetingID = "Not found";
if (preg_match('/MeetingID=([0-9]+)/', $description, $matches)) {
$meetingID = $matches[1];
}
echo "Meeting ID is " . $meetingID;
// this prints 773 or Not found if $description does not contain a (numeric) MeetingID value
There is a very easy way to do it:
Your Str:
$str ='<a target="_blank" href="CoverSheet.aspx?ItemID=18833&MeetingID=773">Description</a><br>';
Make substr:
$params = substr( $str, strpos( $str, 'ItemID'), strpos( $str, '">') - strpos( $str, 'ItemID') );
You will get substr like this :
ItemID=18833&MeetingID=773
Now do whatever you want to do!
Related
I am making a server statistics page in PHP and one of my SQL query show the players nickname including his in-game HEX color codes.
e.g of what I get and what I actually want:
#FF0000Nick#00FF00name --> <span id="nickname"><span style="$color[0]">Nick</span><span style="$color[1]">name</span></span>
What i want to do is disociate the colors from the nickname so i can style them in css and make the nickname coloured.
Here is an idea of my actual code, it's basically a table showing other informations but I'll show you the one I use for the nickname:
while($row = mysqli_fetch_array($result)){
$json = $row['data'];
$playerDataTable = json_decode($json);
foreach($playerDataTable as $playerData){
$ingame_nickname = $playerData->nickname;
echo "<div class='playerNames'";
echo "<span>" . $forum_name . "</span>";
echo "<span class='ingame_nickname'>" . $ingame_nickname . "</span>";
echo "</div>";
}
}
Thank you.
I'd suggest you use regular expressions:
$string = "#FF0000Nick#00FF00name";
$tokens = preg_split('/(#[A-Z0-9]{6})/', $string, -1, PREG_SPLIT_DELIM_CAPTURE);
$tokens will be an array of 1, 3, or 5 elements; element 0 will be the part of the username before the first hex code, 1 the first hex code (including '#') with 2 being the part of the text having that color, 3 the second hex code with 4 the part of the name colored like that.
If there's 1 hex code only, $tokens will only contain 3 elements. If there isn't any, $tokens will contain a single element, which is the full uncolored nickname.
echo $tokens[0];
for($x = 1; $x < count($tokens); $x = $x + 2) {
$color = $tokens[$x];
$name_token = $tokens[$x + 1];
echo '<span style="color:' . $color . ';">' . $name_token . '</span>';
}
You should really get your coder to make decent JSON. But however, you can use regex with named capture group
<?php
$json = '{ "nickname": "#FF0000Nick#00FF00name" }';
$data = json_decode($json, true);
$garbledData = $data['nickname'];
// (?<firstHex>\#[A-F0-9]{6}) match and name the match 'firstHex' - look for a hash, then letters a-f or numbers 0-9, with a length of 6 characters
// (?<name>.+) match and name the match 'name' - look for absolutely any characters, any amount
// (?<secondHex>\#[A-F0-9]{6}) match and name the match 'secondHex' - look for a hash, then letters a-f or numbers 0-9, with a length of 6 characters
$regex = '/(?<firstHex>\#[A-F0-9]{6})(?<name>.+)(?<secondHex>\#[A-F0-9]{6})/';
preg_match($regex, $garbledData, $matches);
$firstHex = $matches['firstHex'];
$secondHex = $matches['secondHex'];
$name = $matches['name'];
echo $firstHex . "\n";
echo $secondHex . "\n";
echo $name . "\n";
Output:
#FF0000
#00FF00
Nick
Check it out here https://3v4l.org/qo2gc
Very(!) new to regex but...
I have the following text strings outputted from a $title variable:
A. This is a title
B. This is another title
etc...
I'm after the following:
<span>A.</span> This is a title
<span>B.</span> This is another title
etc...
Currently I have the following code:
$title = $element['#title'];
if (preg_match("([A-Z][\.])", $title)) {
return '<li' . drupal_attributes($element['#attributes']) . ">Blarg</li>\n";
} else {
return '<li' . drupal_attributes($element['#attributes']) . '>' . $output . $sub_menu . "</li>\n";
}
This replaces anything A. through to Z. with Blarg however I'm not sure how to progress this?
In the Text Wrangler app I could wrap regex in brackets and output each argument like so:
argument 1 = \1
argument 2 = \2
etc...
I know I need to add an additional regex to grab the remainder of the text string.
Perhaps a regex guru could help and novice out!
Thanks,
Steve
Try
$title = 'A. This is a title';
$title = preg_replace('/^[A-Z]\./', '<span>$0</span>', $title);
echo $title;
// <span>A.</span> This is a title
If the string contains newlines and other titles following them, add the m modifier after the ending delimiter.
If the regex doesn't match then no replacements will be made, so there is no need for the if statement.
Is it always just 2 char ("A.", "B.", "C.",...)
because then you could work with a substring instead of regex.
Just pick of the first 2 chars of the link and wrap the span around the substring
Try this (untested):
$title = $element['#title'];
if (preg_match("/([A-Z]\.)(.*)/", $title, $matches)) {
return '<li' . drupal_attributes($element['#attributes']) . "><span>{$matches[0]</span>{$matches[1]}</li>\n";
} else {
return '<li' . drupal_attributes($element['#attributes']) . '>' . $output . $sub_menu . "</li>\n";
}
The change here was to first add / to the start and end of the string (to denote it's a regex), then remove the [ and ] around the period . because that's just a literal character on its own, then to add another grouping which will match the rest of the string. I also Added a $matches to preg_match() to place these two matches in to to use later, which we do on the next life.
Note: You could also do this instead:
$title = preg_replace('/^([A-Z]\.)/', "<span>$1</span>", $title);
This will simply replace the A-Z followed by the period at the start of the string (denoted with the ^ character) with <span>, that character (grabbed with the brackets) and </span>.
Again, that's not tested, but should give you a headstart :)
I'm making this chat server, but it doesn't work quite well. When you send a piece of text, it first gets encoded by the function base64_encode() and then gets sent to a MySQL database.
Then the receiver gets the text from that same MySQL database, which is of course first decoded by the function base64_decode().
The only problem is with the special characters like \n \' and \t: when I get the data from the database and print it between two textarea tags, I see \n as a string, and not as actual line breaks.
In short, I need to fix this problem:
$String = 'Line 1 \n Line 2';
print '<textarea>' . $String . '</textarea>';
//The result I want
//<textarea> Line 1
//Line 2 </textarea>
The function nl2br doesn't work, because tags inside a textarea tag won't work, and also because there other characters like apostrophes.
Could anybody help me?
Thanks!
You need to enclose your string into double quotes, for special characters to be evaluated.
$String = "Line 1 \n Line 2";
print '<textarea>' . $String . '</textarea>';
If you change this:
$String = 'Line 1 \n Line 2';
print '<textarea>' . $String . '</textarea>';
to this:
$String = "Line 1 \n Line 2"; // double quote
print '<textarea>' . $String . '</textarea>';
... you will get the output you want.
This one is also works same as using " ... ", however maybe helps in your case:
$string = <<<EOT
Line 1 \n Line 2
EOT;
echo '<textarea>' . $string . '</textarea>';
As the others said, your problem is Single-Quotes.
The following code gives me the following:
$getexpenses = "SELECT sum(expense_amount) FROM projects_expense WHERE project_id=$project_id";
$showexpenses = #mysqli_query ($dbc, $getexpenses); // Run the query.
echo ' . $showexpenses . ';
Gives me a result of
' . $showexpenses . '
instead of the actual sum...
I'm sure it's something simple I'm missing... thanks!
echo " . $showexpenses . " will work for you. You need double quotes, not single.
I added a call to mysqli_fetch_assoc($showexpenses)to make it fully functional.
I also sanitized $project_id to avoid injections and used an alias to make the sum accessible through an associative array.
$getexpenses = "SELECT SUM(`expense_amount`) as `sum_amount` FROM `projects_expense` WHERE `project_id`= ".intval($project_id);
$showexpenses = mysqli_query ($dbc, $getexpenses);
$sums = mysqli_fetch_assoc($showexpenses);
$sum = $sums['sum_amount'];
echo $sum;
We could also have used mysqli_fetch_row like this:
$getexpenses = "SELECT SUM(`expense_amount`) FROM `projects_expense` WHERE `project_id`= ".intval($project_id);
$showexpenses = mysqli_query ($dbc, $getexpenses);
$sums = mysqli_fetch_row($showexpenses);
$sum = $sums[0];
echo $sum;
The alias is not needed anymore since we know the first column (0) is a match.
NB: you probably also need to GROUP BY project_id if you want to use SUM()
use
echo $showexpenses;
or
echo "My query is: {$showexpenses}";
Further to Nik's response, PHP treats strings differently based on whether you use Single Quotes or Double Quotes around them.
Single-Quotes interpret text as literal text except for '\'' which would output a single quote mark and '\' which would output a slash mark. For this reason, using single quotes would output your variable name instead of the value.
Examples:
CODE | OUTPUT
-----------------+------------------
echo '\t'; | \t
echo '\r'; | \r
echo '$foo'; | $foo
Double-Quotes interpret certain escape sequences for special characters and also interpret variables. For instance, "\n" ouputs a linefeed and "\r" outputs a carriage return. For this reason, echoing "$myvariable" outputs the value instead of the variable name.
Examples:
CODE | OUTPUT
-----------------+------------------
echo "\t"; | {tab space}
echo "\r"; | {carriage return}
echo "$foo"; | bar
More reading: http://www.php.net/manual/en/language.types.string.php
I need to convert single line comments (//...) to block comments (/*...*/). I have nearly accomplished this in the following code; however, I need the function to skip any single line comment is already in a block comment. Currently it matches any single line comment, even when the single line comment is in a block comment.
## Convert Single Line Comment to Block Comments
function singleLineComments( &$output ) {
$output = preg_replace_callback('#//(.*)#m',
create_function(
'$match',
'return "/* " . trim(mb_substr($match[1], 0)) . " */";'
), $output
);
}
As already mentioned, "//..." can occur inside block comments and string literals. So if you create a small "parser" with the aid f a bit of regex-trickery, you could first match either of those things (string literals or block-comments), and after that, test if "//..." is present.
Here's a small demo:
$code ='A
B
// okay!
/*
C
D
// ignore me E F G
H
*/
I
// yes!
K
L = "foo // bar // string";
done // one more!';
$regex = '#
("(?:\\.|[^\r\n\\"])*+") # group 1: matches double quoted string literals
|
(/\*[\s\S]*?\*/) # group 2: matches multi-line comment blocks
|
(//[^\r\n]*+) # group 3: matches single line comments
#x';
preg_match_all($regex, $code, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
foreach($matches as $m) {
if(isset($m[3])) {
echo "replace the string '{$m[3][0]}' starting at offset: {$m[3][1]}\n";
}
}
Which produces the following output:
replace the string '// okay!' starting at offset: 6
replace the string '// yes!' starting at offset: 56
replace the string '// one more!' starting at offset: 102
Of course, there are more string literals possible in PHP, but you get my drift, I presume.
HTH.
You could try a negative look behind: http://www.regular-expressions.info/lookaround.html
## Convert Single Line Comment to Block Comments
function sinlgeLineComments( &$output ) {
$output = preg_replace_callback('#^((?:(?!/\*).)*?)//(.*)#m',
create_function(
'$match',
'return "/* " . trim(mb_substr($match[1], 0)) . " */";'
), $output
);
}
however I worry about possible strings with // in them. like:
$x = "some string // with slashes";
Would get converted.
If your source file is PHP, you could use tokenizer to parse the file with better precision.
http://php.net/manual/en/tokenizer.examples.php
Edit:
Forgot about the fixed length, which you can overcome by nesting the expression. The above should work now. I tested it with:
$foo = "// this is foo";
sinlgeLineComments($foo);
echo $foo . "\n";
$foo2 = "/* something // this is foo2 */";
sinlgeLineComments($foo2);
echo $foo2 . "\n";
$foo3 = "the quick brown fox";
sinlgeLineComments($foo3);
echo $foo3. "\n";;