remove msisdn element based on regex - regex

I'm trying to remove msisdn field from MO calls on TAP3.11, but it doesn't handle the needed.
I want to set a condition, if the Msisdn doesn't start with 962 then remove the element.
My background is only with python, this's the first time with perl. I use it because after searching I believe that only perl can handle TAP files.
# Will scan all the calls for MTC's.
foreach $key ( #{$struct->{'transferBatch'}->{'callEventDetails'} } ) {
foreach ( keys %{$key} ) {
if ( $_ eq "mobileOriginatedCall" )
{
if ( defined $key->{$_}->{'basicCallInformation'} )
{
if ( defined $key->{$_}->{'basicCallInformation'}->{'chargeableSubscriber'} )
{
if ( defined $key->{$_}->{'basicCallInformation'}->{'chargeableSubscriber'}->{'simChargeableSubscriber'})
{
if ( defined $key->{$_}->{'basicCallInformation'}->{'chargeableSubscriber'}->{'simChargeableSubscriber'}->{'msisdn'})
{
if ($key->{$_}->{'basicCallInformation'}->{'chargeableSubscriber'}->{'simChargeableSubscriber'}->{'msisdn'} =~ /^[962]/)
{
$key->{$_}->{'basicCallInformation'}->{'chargeableSubscriber'}->{'simChargeableSubscriber'}->{'msisdn'}=();
}
}
}
}
}
}
}
}

Try with:
...
if ($key->{$_}->{'basicCallInformation'}->{'chargeableSubscriber'}->{'simChargeableSubscriber'}->{'msisdn'} =~ /^(?!962)/)
{
delete $key->{$_}->{'basicCallInformation'}->{'chargeableSubscriber'}->{'simChargeableSubscriber'}->{'msisdn'};
}
The changes:
For deleting a key, use delete
For a "not starting with" regex, use: ^(?!WHATEVER), for example ^(?!962)

Related

How can I elegantly handle state when parsing line oriented files using regex?

I have a perl script that I use to extract data from a raw data/log file. I need help on making the script dynamic. First, let me show you the part of the perl script and raw data file.
Perl script:
if ( /Catalyst tester (\S+)\S+/ )
{
$DETAILS{tester_name} = $1;
}
if ( /(CATALYST_TH\s*1)/ )
{
$FOUND_CAT = 1;
$DETAILS{test_head} = $1;
$TEST_HEAD = $1;
}
if ($FOUND_CAT)
{
if ( /(BACKPLANE\s*A)/ )
{
$FRAME = $TEST_HEAD .' '. $1;
$FOUND_BACKPLANE_A = 1;
}
if ( /(BACKPLANE\s*B)/ )
{
$FRAME = $TEST_HEAD . ' ' . $1;
$FOUND_BACKPLANE_B = 1;
}
}
if ( /END/ )
{
$FOUND_CAT = 0;
$FOUND_BACKPLANE_A = 0;
$FOUND_BACKPLANE_B = 0;
$FOUND_PRECISION_1 = 0;
$FOUND_PRECISION_2 = 0;
$FOUND_UB_SPS = 0;
$FOUND_HSD100_1 = 0;
$FOUND_HSD100_2 = 0;
$FOUND_HSD100_3 = 0;
$FOUND_TSY = 0;
$FOUND_TIME_SUB = 0;
}
if ($FOUND_BACKPLANE_A)
{
if ( /(\d+)\s+(\S+)\s+(\w+)\s+\w+\s+\d*\s+\#\s+\S+\s+(?:\d+\s+){2}((?!.*EMPTY\b).+)$/ )
{
push #{$DETAILS{frame}}, $FRAME;
push #{$DETAILS{slot}}, $1;
push #{$DETAILS{part_no}}, $2;
push #{$DETAILS{serial_no}}, $3;
push #{$DETAILS{board_name}}, $4;
}
}
if ($FOUND_BACKPLANE_B)
{
if ( /(\d+)\s+(\S+)\s+(\w+)\s+\w+\s+\d*\s+\#\s+\S+\s+((?!.*EMPTY\b).+)$/ )
{
push #{$DETAILS{frame}}, $FRAME;
push #{$DETAILS{slot}}, $1;
push #{$DETAILS{part_no}}, $2;
push #{$DETAILS{serial_no}}, $3;
push #{$DETAILS{board_name}}, $4;
}
}
if( /(PRECISION\_AC\s*1)/ )
{
$FOUND_PRECISION_1 = 1;
$FRAME = $1;
}
if ($FOUND_PRECISION_1)
{
if ( /(\d+)\s+(\S+)\s+(\w+)\s+\w+\s+\d*\s+\#\s+\S+\s+((?!.*EMPTY\b).+)/ )
{
push #{$DETAILS{frame}}, $FRAME;
push #{$DETAILS{slot}}, $1;
push #{$DETAILS{part_no}}, $2;
push #{$DETAILS{serial_no}}, $3;
push #{$DETAILS{board_name}}, $4;
}
}
## And the rest of the script follows the same format
In my perl script, my logic is if the line/word/header(as I prefer to call it) is found, assign a variable with a true or 1. Then in another if statement if the variable is 1, search for the data needed using regex and store it in a hash.
Now my main problem is that it is not dynamic. If you noticed I did an if statement for every header and the variable that is used to store a 1 is different for every header; if it's Catalyst tester then the variable would be $FOUND_CAT = 1;.
Somethings to take note of: for the header specifically CATALYST_TH 1, there will always be BACKPLANE A or it could be BACKPLANE B. If there is a BACKPLANE B I would have to write another if statement and push everything into the hash again. It's tedious because other log files may have even up to C or D which I do not know of yet, therefore making my script hard to maintain.
Other headers only need one line like PRECISION_AC 1. Only CATALYST_TH 1 will always have a backplane. This is just to take note in case it affects any answers.
So any help on this? Is there anyway to reduce the number of variables? Or even the number or if statements? I've tried but that way it wouldn't push other data into the hash if it's not true. Suggestions would greatly be appreciated.
P.S. Ignore the comments with one '#' symbol, those are part of the log file. The ones with two '#' symbols, like '##' are the comments I have added in.
Since your parsing has lots of state in it depending on what your program has already seen I would switch from regex to Parse-RecDescent, which can easily handle all that state nicely.
It's a steep learning curve at first though. There's a tutorial on it here, and an older, simpler tutorial here.

How to remove asterisk from this spin syntax code?

here is my code it is a text spinner (synonym)
public function fetchContent($keyword)
{
$customContent = $this->getOption('custom_content_text');
$this->_setHttpStatusCode(200);
if (!$customContent)
{
$this->_setContentStatus(self::CONTENT_STATUS_NO_RESULTS);
return false;
}
if (preg_match_all('/({\*)(.*?)(\*})/', $customContent, $result))
{
if (is_array($result[0]))
{
foreach ($result[0] as $index => $group_string)
{
//replace the first or next pattern match with a replaceable token
$customContent = preg_replace('/(\{\*)(.*?)(\*\})/', '{#'.$index.'#}', $customContent, 1);
$words = explode('|', $result[2][$index]);
//clean and trim all words
$finalPhrase = array();
foreach ($words as $word)
{
if (preg_match('/\S/', $word))
{
$word = preg_replace('/{%keyword%}/i', $keyword, $word);
$finalPhrase[] = trim($word);
}
}
$finalPhrase = $finalPhrase[rand(0, count($finalPhrase) - 1)];
//now inject it back to where the token was
$customContent = str_ireplace('{#' . $index . '#}', $finalPhrase, $customContent);
}
$this->_setContentStatus(self::CONTENT_STATUS_PASSED);
}
}
return $customContent;
}
}
there is regex that request bracket like this
{*spin1|spin2|spin3*}
here is the regex from the snippet above
if (preg_match_all('/({\*)(.*?)(\*})/', $customContent, $result))
$customContent = preg_replace('/(\{\*)(.*?)(\*\})/', '{#'.$index.'#}', $customContent, 1);
i would like to remove the * to format allow just {spin1|spin2|spin3} wich is more compatible with most spinner ,
i tried with some regex that i find online
i tried to remove the * from both regex without result
thanks you very much for your help
Remove \* instead of just * – Lucas Trzesniewski

Parsing Microsoft Office 2013 MRU Lists in Registry using Perl

I am currently trying to parse the keys in a Windows 7 registry containing the MRU lists for Microsoft Office 2013. However when I attempt to run the Perl script in RegRipper it says the plugin was not successfully run. Im not sure if there is a syntax error in my code or if it is unable to parse the registry as I have it written. The biggest problem is that one of the keys is named after the user's LiveId (it appear as LiveId_XXXXXXX) and this changes from user to user so i would like this plugin to work no matter what the user's LiveId is. Thanks!
my $reg = Parse::Win32Registry->new($ntuser);
my $root_key = $reg->get_root_key;
# ::rptMsg("officedocs2013_File_MRU v.".$VERSION); # 20110830 [fpi] - redundant
my $tag = 0;
my $key_path = "Software\\Microsoft\\Office\\15.0";
if (defined($root_key->get_subkey($key_path))) {
$tag = 1;
}
if ($tag) {
::rptMsg("MSOffice version 2013 located.");
my $key_path = "Software\\Microsoft\\Office\\15.0";
my $of_key = $root_key->get_subkey($key_path);
if ($of_key) {
# Attempt to retrieve Word docs
my $word_mru_key_path = 'Software\\Microsoft\\Office\\15.0\\Word\\User MRU';
my $word_mru_key = $of_key->get_subkey($word_mru_key_path);
foreach ($word_mru_key->get_list_of_subkeys())
{
if ($key->as_string() =~ /LiveId_\w+/)
{
$word = join($key->as_string(),'\\File MRU');
::rptMsg($key_path."\\".$word);
::rptMsg("LastWrite Time ".gmtime($word_key->get_timestamp())." (UTC)");
my #vals = $word_key->get_list_of_values();
if (scalar(#vals) > 0) {
my %files
# Retrieve values and load into a hash for sorting
foreach my $v (#vals) {
my $val = $v->get_name();
if ($val eq "Max Display") { next; }
my $data = getWinTS($v->get_data());
my $tag = (split(/Item/,$val))[1];
$files{$tag} = $val.":".$data;
}
# Print sorted content to report file
foreach my $u (sort {$a <=> $b} keys %files) {
my ($val,$data) = split(/:/,$files{$u},2);
::rptMsg(" ".$val." -> ".$data);
}
}
else {
::rptMsg($key_path.$word." has no values.");
}
else {
::rptMsg($key_path.$word." not found.");
}
::rptMsg("");
}
}
The regex
LiveId_(\w+)
will grab the string after LiveId_ and you can reference it with a \1 like this

Symfony2 Doctrine2 : querybuilder bad query

New to Symfony2 and Doctrine2, i have a function in my entity repository to search entities after form submission. Input is array $get that contain form fields like $get['name'] = 'aname'.
My problem is that when i request with an id, or an id and a name, it's ok by with only a name, all my entities are matched because the query that has been build have no where clause.
Here is my code :
public function search(array $get, $flag = False){
/* Indexed column (used for fast and accurate table cardinality) */
$alias = 'd';
/* DB table to use */
$tableObjectName = 'mysiteMyBundle:DB';
$qb = $this->getEntityManager()
->getRepository($tableObjectName)
->createQueryBuilder($alias)
->select($alias.'.id');
$arr = array();
//Simple array, will grow after problem solved
$numericFields = array(
'id');
$textFields = array(
'name');
while($el = current($get)) {
$field = key($get);
if ( $field == '' or $field == Null or $el == '' or $el == Null ) {
next($get);
}
if ( in_array($field,$numericFields) ){
if ( is_numeric($el) ){
$arr[] = $qb->expr()->eq($alias.".".$field, $el);
}
} else {
if ( in_array($field,$textFields) ) {
$arr[] = $qb->expr()->like($alias.".".$field, $qb->expr()->literal('%'.$el.'%') );
}
}
next($get);
}
if(count($arr) > 0) $qb->andWhere(new Expr\Orx($arr));
else unset($arr);
$query = $qb->getQuery();
if($flag)
return $query;
else
return $query->getResult();
}
The query generated with only a name (ex "myname") input is :
SELECT d0_.id AS id0 FROM DB d0_
It should be:
SELECT d0_.id AS id0 FROM DB d0_ WHERE d0_.name LIKE '%myname%'
What's wrong with my code ?
Thanks !
I don't know if it's related, but do not use "OR" or "AND" operators, because they have a different meaning that the classic "&&" or "||". cf http://php.net/manual/en/language.operators.logical.php
So, first, replace "AND" by "&&", and "OR" by "||".
you should use the setParameter method
$query->where('id = :id')->setParameter('id', $id);

How can I read a custom defined pattern from a file in Perl?

Advance New Year Wishes to All.
I have an error log file with the contents in a pattern parameter, result and stderr (stderr can be in multiple lines).
$cat error_log
<parameter>:test_tot_count
<result>:1
<stderr>:Expected "test_tot_count=2" and the actual value is 3
test_tot_count = 3
<parameter>:test_one_count
<result>:0
<stderr>:Expected "test_one_count=2" and the actual value is 0
test_one_count = 0
<parameter>:test_two_count
<result>:4
<stderr>:Expected "test_two_count=2" and the actual value is 4
test_two_count = 4
...
I need to write a function in Perl to store each parameters, result and stderr in an array or hash table.
This is our own internally defined structure. I wrote the Perl function like this. Is there a better way of doing this using regular expression itself?
my $err_msg = "";
while (<ERR_LOG>)
{
if (/<parameter>:/)
{
s/<parameter>://;
push #parameter, $_;
}
elsif (/<result>:/)
{
s/<result>://;
push #result, $_;
}
elsif (/<stderr>:/)
{
if (length($err_msg) > 0)
{
push #stderr, $err_msg;
}
s/<stderr>://;
$err_msg = $_;
}
else
{
$err_msg .= $_;
}
}
if (length($err_msg) > 0)
{
push #stderr, $err_msg;
}
If you're using Perl 5.10, you can do something very similar to what you have now but with a much nicer layout by using the given/when structure:
use 5.010;
while (<ERR_LOG>) {
chomp;
given ($_) {
when ( m{^<parameter>: (.*)}x ) { push #parameter, $1 }
when ( m{^<result>: (.*)}x ) { push #result, $1 }
when ( m{^<stderr>: (.*)}x ) { push #stderr, $1 }
default { $stderr[-1] .= "\n$_" }
}
}
It's worth noting that for the default case here, rather than keeping a separate $err_msg variable, I'm simply pushing onto #stderr when I see a stderr tag, and appending to the last item of the #stderr array if I see a continuation line. I'm adding a newline when I see continuation lines, since I assume you want them preserved.
Despite the above code looking quite elegant, I'm not really all that fond of keeping three separate arrays, since it will presumably cause you headaches if things get out of sync, and because if you want to add more fields in the future you'll end up with lots and lots of variables floating around that you'll need to keep track of. I'd suggest storing each record inside a hash, and then keeping an array of records:
use 5.010;
my #records;
my $prev_key;
while (<ERR_LOG>) {
chomp;
given ($_) {
when ( m{^<parameter> }x ) { push(#records, {}); continue; }
when ( m{^<(\w+)>: (.*)}x ) { $records[-1]{$1} = $2; $prev_key = $1; }
default { $records[-1]{$prev_key} .= "\n$_"; }
}
}
Here we're pushing a new record onto the array when we see a field, adding an entry to our hash whenever we see a key/value pair, and appending to the last field we added to if we see a continuation line. The end result of #records looks like this:
(
{
parameter => 'test_one_count',
result => 0,
stderr => qq{Expected "test_one_count=2" and the actual value is 0\ntest_one_count=0},
},
{
parameter => 'test_two_count',
result => 4,
stderr => qq{Expected "test_two_count=2" and the actual value is 4\ntest_two_count=4},
}
)
Now you can pass just a single data structure around which contains all of your records, and you can add more fields in the future (even multi-line ones) and they'll be correctly handled.
If you're not using Perl 5.10, then this may be a good excuse to upgrade. If not, you can translate the given/when structures into more traditional if/elsif/else structures, but they lose much of their beauty in the conversion.
Paul
The main thing that jumps out for refactoring is the repetition in the matching, stripping, and storing. Something like this (untested) code is more concise:
my( $err_msg , %data );
while (<ERR_LOG>) {
if(( my $key ) = $_ =~ s/^<(parameter|result|stderr)>:// ) {
if( $key eq 'stderr' ) {
push #{ $data{$key} } , $err_msg if $err_msg;
$err_msg = $_;
}
else { push #{ $data{$key} } , $_ }
}
else { $err_msg .= $_ }
}
# grab the last err_msg out of the hopper
push #{ $data{stderr} } , $err_msg;
... but it may be harder to understand six months from now... 8^)
Looks nice. =) An improvement is probably to anchor those tags at the beginning of the line:
if (/^<parameter>:/)
It'll make the script a bit more robust.
You can also avoid the stripping of the tag if you catch what's after it and use only that part:
if (/^<parameter>:(.*)/s)
{
push #parameter, $1;
}