What I have done will probably be confusing but I tried doing it by replacing every letter to nothing until it finds a space.
for (int i = 0; i < mening.length(); i++) {
if ((int)mening.charAt(i) != 32 && stop == false) {
mening = mening.replace(String.valueOf(mening.charAt(i)), "");
} else {
stop = true;
break;
}
}
Just split string by space, remove the first item and join the rest together.
mening = mening.split(' ').slice(1).join(' ');
I have this method with a bug that will remove characters before JSON in a string, for example this line of logging output:
Oct 2 21:37:03 ip-172-31-9-171 ubuntu: ["opstop"]
so I have this method to remove the text preceding the JSON:
class TrimJSON {
sliceStr(o: string) {
const ib = o.indexOf('["');
const iz = o.indexOf('{"');
if (ib > 0 || iz > 0) {
let i = Math.min(ib, iz);
console.log({i,iz,ib});
o = o.slice(i);
}
return o;
}
}
and so
console.log(
new TrimJSON()
.sliceStr('Oct 2 21:37:03 ip-172-31-9-171 ubuntu: ["opstop"]')
)
will yield: ']'
since that is the last character. The reason is because of these values:
{ i: -1, iz: -1, ib: 40 }
is there some good way to mitigate this? My solution looks like this and it's pretty ugly:
sliceStr(o: string) {
const ib = o.indexOf('["');
const iz = o.indexOf('{"');
if (ib > 0 && ib >= iz) {
o = o.slice(ib);
}
else if(iz > 0 && iz >= ib){
o = o.slice(ib);
}
console.log('sliced json-stream string:', o);
return o;
}
This assumes there is always a [" or {" in the string, you might want to add a condition for when there isn't or it will just return the last character as you've seen, but this will do it in a pretty concise way:
function trimJSON(log) {
const i = log.indexOf('{"') > -1 ? log.indexOf('{"') : log.indexOf('["');
return log.slice(i);
}
console.log(trimJSON('Oct 2 21:37:03 ip-172-31-9-171 ubuntu: ["opstop"]'));
// ["opstop"]
It's overly complicated to make a class just for that method.
#!/usr/bin/perl
if (! eval "require LWP::UserAgent;")
{
$ret = "LWP::UserAgent not found";
}
if ( exists $ARGV[0]) {
if ($ret)
{
print "no ($ret)\n";
exit 1;
}
my $ua = LWP::UserAgent->new(timeout => 5);
my $response = $ua->request(HTTP::Request->new('GET',$ARGV[0]));
my #content = split (/\n/, $response->content);
my $active_connections = -1;
if ($content[0] =~ /^Active connections:\s+(\d+)\s*$/i) {
$active_connections = $1;
}
my $accepts = -1;
my $handled = -1;
my $requests = -1;
if ($content[2] =~ /^\s+(\d+)\s+(\d+)\s+(\d+)\s*$/) {
$accepts = $1;
$handled = $2;
$requests = $3;
}
my $reading = -1;
my $writing = -1;
my $waiting = -1;
if ($content[3] =~ /Reading: (\d+) Writing: (\d+) Waiting: (\d+)\s*$/) {
$reading = $1;
$writing = $2;
$waiting = $3;
}
print "nginx_active:$active_connections nginx_reading:$reading nginx_writing:$writing nginx_waiting:$waiting ";
print "\n";
}
My nginx status page:
Active connections: 2
server accepts handled requests
2 2 2
Reading: 0 Writing: 1 Waiting: 1
running:
./get_nginx_clients_status.pl http://IP/nginx_status
nginx_active:-1 nginx_reading:-1 nginx_writing:-1 nginx_waiting:-1
I should be getting:
nginx_accepts:113869 nginx_handled:113869 nginx_requests:122594
Any idea what could be wrong?
Your code states:
my $accepts = -1;
my $handled = -1;
my $requests = -1;
And your output is:
nginx_active:-1 nginx_reading:-1 nginx_writing:-1 nginx_waiting:-1
Therefore, because you test:
$content[2] =~ /^\s+(\d+)\s+(\d+)\s+(\d+)\s*$/
... it follows that $content[2] does not contain the information your regular expression demands. Have you tried adding print $content[2] . "\n"; to help debug your script?
The Debugger
Please consider use of the Perl debugger. It will answer obvious problems very quickly for you.
Start your script using the -d flag. Then step through your code one line at a time using n to go to the next line, l to list the code at the current point, and x #content (for example) to list the contents of variables each step of the way.
I have a hard-coded if loops that looks like this:
my $tp = 0;
my $fp = 0;
if ( $myhash{$pred}
|| $myhash{$pred1}
|| $myhash{$pred2}
|| $myhash{$pred3}
|| $myhash{$pred4}
|| $myhash{$pred5}
|| $myhash{$pred6} )
{
$tp++;
}
else {
$fp++;
}
How can I do that in for loops?
I tried the following but it give different result in total of fp and tp:
my $tp=0;
my $fp=0;
my #allpreds = ($pred,$pred1,$pred2,$pred3,$pred4,$pred5);
foreach my $allpred ( #allpreds ) {
if ( $myhash{$allpred} ) {
$tp++;
}
}
if ( !myhash{$pred} ) {
$fp++;
}
my $tp=0;
my $fp=0;
my $count=0;
my #allpreds = ($pred,$pred1,$pred2,$pred3,$pred4,$pred5);
foreach my $allpred ( #allpreds ) {
if ( $myhash{$allpred} ) {
$count++;
}
}
if ($count>0) { $tp=1; } else { $fp=1; }
This is somewhat more compact than some answers, but fully equivalent.
my $tp = 0;
my $fp = 0;
foreach my $allpred ($pred, $pred1, $pred2, $pred3, $pred4, $pred5)
{
$tp++, last if ($myhash{$allpred});
}
$fp = !$tp;
It is not clear that the variable $fp earns its keep when !$tp is almost as simple to write.
Test code - change the settings on the RHS of the fat commas to change the behaviour of the test.
use strict;
use warnings;
my $pred = "";
my $pred1 = "1";
my $pred2 = "2 2";
my $pred3 = "3 3 3";
my $pred4 = "4 4 4 4";
my $pred5 = "5 5 5 5 5";
my %myhash = ( $pred1 => 0, $pred2 => 0, $pred3 => 0, $pred4 => 0, $pred5 => 1 );
my $tp = 0;
my $fp = 0;
foreach my $allpred ($pred, $pred1, $pred2, $pred3, $pred4, $pred5)
{
$tp++, last if ($myhash{$allpred});
}
$fp = !$tp;
printf "%d:%d\n", $tp, $fp;
grep will return a true value when any one or more of its inputs returns true for it's statement, basically allowing it to act like a chain of ||'ed statements, except that it won't short circuit.
my #allpreds = ($pred, $pred1, $pred2, $pred3, $pred4, $pred5, $pred6);
if (grep { $myhash{$_} } #allpreds) {
$tp++;
}
else {
$fp++;
}
Using grep this way can be a bit confusing so a more explicit way is to use List::MoreUtils any
use List::MoreUtils qw(any);
my #allpreds = ($pred, $pred1, $pred2, $pred3, $pred4, $pred5, $pred6);
if (any { $myhash{$_} } #allpreds) {
$tp++;
}
else {
$fp++;
}
I have the following command which displays to me my current IP address:
ifconfig -a | awk 'BEGIN { count=0; } { if ( $1 ~ /inet/ ) { count++; if( count==2 ) { print $2; } } }'
I'd like to be able to wrap this command into an alias such as:
alias myip="ifconfig -a | awk 'BEGIN { count=0; } { if ( $1 ~ /inet/ ) { count++; if( count==2 ) { print $2; } } }'"
or even a function like so:
function myip() { ifconfig -a | awk 'BEGIN { count=0; } { if ( $1 ~ /inet/ ) { count++; if( count==2 ) { print $2; } } }' }
However, none of these solutions work and I get this error:
syntax error near unexpected token ``{ifconfig'
I've tried this:
alias myip='ifconfig -a | awk '\''BEGIN{ count=0; } { if ( $1 ~ /inet/ ) { count++; if( count==2 ) { print $2; } } }'\'''
but no luck.
How would I be able to accomplish this task?
1) Your function needs a ; before the closing }
function myip() { ifconfig -a | awk 'BEGIN { count=0; } { if ( $1 ~ /inet/ ) { count++; if( count==2 ) { print $2; } } }'; }
HERE --^
2) You only need either function or (), but not both. (Although this depends on your shell.)
function myip { ifconfig -a | awk 'BEGIN { count=0; } { if ( $1 ~ /inet/ ) { count++; if( count==2 ) { print $2; } } }'; }
3) You probably didn't unalias your previous attempt before you did your function attempt
unalias myip
After making those changes, the function should work without a syntax error.