d5e5 109 Master Poster

I think the problem is that your CASE statement is evaluating to the number 1 instead of the string that you want for completing your WHERE condition. Look at this example:

mysql> select '07:20:00' AND '15:19:59' as shift;
+-------+
| shift |
+-------+
|     1 | 
+-------+

See? The result is 1 instead of '07:20:00' AND '15:19:59'. Put double quotes around the result to get a string:

mysql> select "'07:20:00' AND '15:19:59'" as shift;
+---------------------------+
| shift                     |
+---------------------------+
| '07:20:00' AND '15:19:59' | 
+---------------------------+
d5e5 109 Master Poster

good day! im an IT student. im new to php&mysql. my database engine is first myisam. everything works fine. but when i changed it into innodb(for foreign key purposes) i can't insert a data in my the parent table. i can insert data in child table though. replies are really appreciated! help me pls.!

I believe that which database engine a table uses is determined for each table, not for the entire database. When you create a table without specifying the database engine the table uses myisam by default. Are you sure you changed both your parent and your child table to innodb (you say you changed "it" rather than "them")?

It may help if you post a description of the tables here. For example, from the MySQL command line (not in PHP):

mysql> SHOW CREATE TABLE people;
+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table  | Create Table                                                                                                                                                                                               |
+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| people | CREATE TABLE `people` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(25) DEFAULT NULL,
  `dob` date DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 | 
+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
d5e5 109 Master Poster

Thanks for the link Mike. One of my favourites is $. although I haven't managed to use it much yet. $. Is not a regex variable but here is an example of using it to identify the line numbers where a regex match succeeds.

#!/usr/bin/perl
use strict;
use warnings;

while (<DATA>){
    if (m/\bcane\b/){
        #The following statement uses the special variable $.
        #which contains the current line number of the input file
        print "Line number $. of the file contains the word $&.\n";
    }
}

__DATA__
The Spring blew trumpets of color;
Her Green sang in my brain --
I heard a blind man groping
"Tap -- tap" with his cane;

I pitied him in his blindness;
But can I boast, "I see"?
Perhaps there walks a spirit
Close by, who pities me, --

A spirit who hears me tapping
The five-sensed cane of mind
Amid such unguessed glories --
That I am worse than blind.

This prints the following:

Line number 4 of the file contains the word cane.
Line number 12 of the file contains the word cane.
d5e5 109 Master Poster
#!/usr/bin/perl
use strict;
use warnings;

#I'm reading my __DATA__ section but you can open your file
# instead and slurp it as follows: (I don't read a list of duplicates, only the first file)
undef $/;
my $whole_file = <DATA>; # 'slurp' mode
$/ = "\n"; #Put it back the way it was

#regular expression substitute in multi-line and global mode
$whole_file =~ s/^(\w+)([^\n]+\n)(?=\1)/$1.1$2/mg;
print $whole_file;

__DATA__
ID Entry Entry
1 0 0
2 1 0
2 0 1
3 1 1
4 0 0
4 0 0

This gives the following output:

ID Entry Entry
1 0 0
2.1 1 0
2 0 1
3 1 1
4.1 0 0
4 0 0
mitchems commented: David - that's just an awesome regex! +2
d5e5 109 Master Poster

I used my @port = qw(80 70 1083 42); to build myself an array for testing. qw() puts quotes around the space-delimited items you give it as arguments. The array you build by pushing values into it should work just as well.

As for how to retrieve the keys from the hash after it has been built I had a difficult time with that so may not have found the best way. But, how about the following? I couldn't get it to work at all until I changed your my $referenceTable to my %referenceTable and then slavishly followed one of examples at http://perldoc.perl.org/perldsc.html#HASHES-OF-HASHES.

#!/usr/bin/perl
use strict;
use warnings;

my @port = qw(80 70 1083 42);
my ( $key1, $key2 ) = ( 'First Key', 'Second Key' );
my %referenceTable; #Declare a hash, not a reference.

foreach (@port) {
    undef $referenceTable{$key1}{$key2}{$_};
}

foreach my $x ( keys %referenceTable ) {
    print "Hash key is $x and ";
    for my $y ( keys %{ $referenceTable{$x} } ) {
        print "$y \n";
        print "Keys for hash stored in this hash are:\n";
        for my $z ( keys %{ $referenceTable{$x}{$y} }){
            print "$z\n";
        }
    }
}

This gives the following output:

Hash key is First Key and Second Key 
Keys for hash stored in this hash are:
42
70
1083
80
d5e5 109 Master Poster

I don't know how to print what you want yet but to figure it out I might start by using Data::Dumper to print the data structure and values.

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;

my $referenceTable;
my @port = qw(80 70 1083 42);
my ( $key1, $key2 ) = ( 'First Key', 'Second Key' );

foreach (@port) {
    undef $referenceTable->{$key1}->{$key2}->{$_};
}

print Dumper($referenceTable);

Prints the following:

$VAR1 = {
          'First Key' => {
                           'Second Key' => {
                                             '42' => undef,
                                             '70' => undef,
                                             '1083' => undef,
                                             '80' => undef
                                           }
                         }
        };
d5e5 109 Master Poster

There should be a way to incorporate a CASE expression into your UPDATE query. Also, consider using BETWEEN min AND max.

d5e5 109 Master Poster

You only need one query which you run once. Then you fetch the results into an array and loop over the array.

<?php
require('includes/init_mysql.php');
$con = mysql_connect($db_host,$db_user,$db_pass);
if (!$con)
  {
  die('Could not connect: ' . mysql_error());
  }

mysql_select_db("daniweb", $con);

$key = array('Cable Guy', 'John Doe');
foreach($key as $value){
    $dr[] = "name = '$value' "; // Build array of strings
}
$sql = "SELECT * FROM people WHERE ";
$sql .= implode(' OR ', $dr); // convert to string joined by ' OR ' and add to end of $sql

// Instead of using a loop and running a query for 'Cable Guy'
// and another query for 'John Doe', the following query fetches both rows.
$result = mysql_query($sql);

while($row = mysql_fetch_array($result))
  {
  echo $row['name'] . " " . $row['dob'];
  echo "<br />";
  }

mysql_close($con);
?>
d5e5 109 Master Poster

Yes, you need to have write permission for the file you want to delete, and according to a poster at the following link: "The folder that contains the file must ALSO have write permission."

d5e5 109 Master Poster

I don't see the need to record rank in your database table because you can calculate it from the scores, right? Plus I would not put the teams in different columns on one record because that makes it difficult to write queries on the data. I think a table like the following would save all the data that you need to calculate totals and rank:

mysql> select * from scores;
+----------+------+-----+-----+
| match_id | team | FOO | BAR |
+----------+------+-----+-----+
|        1 |    1 |   2 |   5 | 
|        1 |    2 |   6 |   3 | 
|        1 |    3 |   4 |   7 | 
+----------+------+-----+-----+
d5e5 109 Master Poster

ghosh22: Make sure your input file is really tab-delimited (see attached file) rather than space-delimited. mitchems already pointed this out, but some text editors make it hard to see the difference so you may not have understood what he meant.

mitchems: I added a line to your script to satisfy the warnings pragma.

...snip...
    ($chem,$react)=split(/\t/);
    #Add the following line to make the warnings pragma happy
    $property{$chem} = '' if not exists $property{$chem};
    print OUT "$chem\t$react\t$property{$chem}\n";
.../snip...
d5e5 109 Master Poster
#!/usr/bin/perl
#print_last_2_lines.pl
use strict;
use warnings;

my $previous; #Declare $previous and $latest outside the loop
my $latest;   # because we want to print them outside the loop

while (<DATA>){ #Loop through file, saving last two lines
    $previous = $latest;
    $latest = $_;
}
print $previous, $latest;

__DATA__
StartTimeStamp,EndTimeStamp,counter1,counter2
Aug15 2010 22:45:43,Aug15 2010 23:00:00,6,0
Aug15 2010 23:00:00,Aug15 2010 23:07:43,3,0
Aug15 2010 24:00:00,Aug15 2010 24:07:43,8,0
Aug15 2010 25:00:00,Aug15 2010 25:07:43,2,0
d5e5 109 Master Poster
<?php
function string_of_xes($matches)
{
  // as usual: $matches[0] is the complete match
  $r = str_repeat('x', strlen($matches[0]));
  return $r;
}

$pattern = '/0{5,}/';
$string = '11000001100010011000001';
//Replace all strings of 0's with length 5 or longer with same # of x's
$temp1 = preg_replace_callback($pattern, string_of_xes, $string);
echo $temp1 . "\n";

//Replace all remaining 0's with 1's
$pattern = '/0/';
$temp2 = preg_replace($pattern, '1', $temp1);
echo $temp2 . "\n";

//Restore the x's back to 0's
$pattern = '/x/';
$string_out = preg_replace($pattern, '0', $temp2);
echo $string_out;
?>

Output is

11xxxxx1100010011xxxxx1
11xxxxx1111111111xxxxx1
11000001111111111000001
d5e5 109 Master Poster

In general I would try to tailor the complexity of the solution and extent of explanation to the apparent knowledge level of the person posing the question. However, figuring out what the poster needs to know is a two-way street. If someone posts a vague and hastily-written question and never adds any more comments or feedback, what can you do? If the question interests me and I can come up with a not-too-elaborate way to test my answer, I'll take a shot at it.

If the poster gives some further details or clarification I tend to make more effort to help than when someone just pops a question and disappears.

I'm really not sure what neerajte wanted. Names and addresses are not unique in the real world and keys to a hash have to be unique, but your solution works for the sample data and demonstrated the principle of using an array of hashes, so it may have served the purpose. If neerajte doesn't reply or mark the thread solved, we won't know for sure.

d5e5 109 Master Poster

Yes, that problem arises because the script counts each item as it prints to the browser so the total doesn't exist before the items have already been displayed. Ideally, someone could rewrite the entire script to do all the calculations separately before creating the html output; but that would take a lot of work.

I think the easiest thing to do at this point would be to first print the all the html output to a string variable before printing it to the browser. After the total has been calculated you can put it in the string variable in the desired place near the beginning (i.e. near the top of the page) of the string, perhaps by searching for and replacing a place-holder literal such as !!!ReplaceThis!!!. Then you can print the string variable, thereby sending all the web page content to the browser.

An example of printing to a string variable (i.e. printing to memory):

#!/usr/bin/perl
use strict;
use warnings;

my $buffer; #Instead of printing directly to STDOUT, print to this variable, first

open(MEMORY,'>', \$buffer)
     or die "Can't open memory file: $!";

print MEMORY "The total number of lines to print (not counting this one) is !!!TOTAL_GOES_HERE!!!.\n";
my $The_Count = 0; #Ready to start counting each line as we print it
print MEMORY "Program prints all this to memory first.\n"; # output will appear in $buffer
$The_Count++;
print MEMORY "Here's another line.\n";
$The_Count++;

#Replace the placeholder in string variable with $The_Count
$buffer =~ s/!!!TOTAL_GOES_HERE!!!/$The_Count/;
#Now that …
d5e5 109 Master Poster

I don't have an answer of my own but someone asked the same question on http://stackoverflow.com/questions/2637945/getting-relative-path-from-absolute-path-in-php and the answers seemed to involve doing pretty much what you're doing, i.e. writing a function to do it. You may want to have a look at the proposed solutions there and compare them to yours.

d5e5 109 Master Poster

Hi,

I've modified the code like this : if the option value is less than 100 add a zero in front it. eg: if $opt1 is 23 it should become 023.

i execute my script like this (without including the opt3) : my_script -opt1 80 -opt2 23

foreach my $val (@opt)
   { 
      if (defined $val and $$val < 100 and $$val != 0)
      { 
         $$val = sprintf("0%d",$$val); 
      }
      print "Check : $$val\n"; 
   }

The code works fine. But it gives some warnings (i have used all the headers that you have used).

Use of uninitialized value in numeric lt (<) at ./fun line 417.
Use of uninitialized value in numeric ne (!=) at ./fun line 417.

Can u clarify this.

Now you are only giving two options, but are you still defining three options, like this?
#our @opt = ( \$opt1, \$opt2, \$opt3 ); #Defining THREE options

If so, when you loop through the @opt array, you will get a warning because you are trying to compare and concatenate \$opt3 which receives nothing from the command line parameters.

Apparently, $val is always defined in your loop, so your test doesn't stop the warning. It is $$val which is not defined because \$opt3 sometimes has no value. The following runs OK for me:

#!/usr/bin/perl
#getopt04.pl
use strict;
use warnings;

use Getopt::Long;
#our ($opt1, $opt2, $opt3); 
#our @opt = ( \$opt1, \$opt2, \$opt3 ); #Defining THREE options
our ($opt1, $opt2); 
our @opt = ( …
d5e5 109 Master Poster
#!/usr/bin/perl
#getopt03.pl
use strict;
use warnings;

use Getopt::Long;
our ($opt1, $opt2, $opt3);
our @opt = ( \$opt1, \$opt2, \$opt3 );
GetOptions(
    'opt1=i' => \$opt1,
    'opt2=i' => \$opt2,
    'opt3=i' => \$opt3
);

check();
## I don't see a problem. The actual options do reflect the changes.
print "The actual values of the options are:\n"
        . "opt1 = $opt1\n"
        . "opt2 = $opt2\n"
        . "opt3 = $opt3\n";
        
sub check {
    foreach (@opt) {
        if ( $$_ < 100 ) {
            $$_ = 100;
        }
    }
}

Running the above script on the command line gives the following output:

perl getopt03.pl --opt1=150 --opt2=24 --opt3=32
The actual values of the options are:
opt1 = 150
opt2 = 100
opt3 = 100
d5e5 109 Master Poster
<?php
$ct = array (
             "a" => 1,
             "b" => 2,
             "z" => 2,
             "c" => 1
            );

$con = mysql_connect('localhost','david','mypwd');
if (!$con)
  {
  die('Could not connect: ' . mysql_error());
  }

mysql_select_db("daniweb", $con);

foreach($ct as $item => $count){
    $sql = "INSERT INTO test2(item,ct) VALUES ('$item', $count)";
    if ($result = mysql_query($sql)) {
        echo "One row inserted for $item\n";
    }
    else {
        echo "Failed to insert $item\n";
    }
}

mysql_close($con);
?>
d5e5 109 Master Poster

First, make a small change to your print_result subroutine (really, just uncomment a line that was commented out).

sub print_result
{
    my ($baseurl, $file, $title) = @_;

    $file    =~ s#^/##;
    $baseurl =~ s#/$##;
 
    $The_Count++; #Add one to your count of recipes listed

    print qq(<li><a href="$E{"$baseurl/$file"}">$E{$title}</a></li>\n);
}

Second thing to do is scroll down to around line 230 of your script and change the code that looks like this: (Notice the one line I added to print $The_Count.)

if (!$emulate_matts_code)
    {
        my @base = sort {$hits[$b] <=> $hits[$a]} (0 .. $#hits);
        @titles  = @titles[@base];
        @paths   = @paths[@base];

        for my $i (0 .. $#hits)
        {
           print_result($baseurl, $paths[$i], $titles[$i])
                 if ($hits[$i] >= $hit_threshhold);
        }
    }
    print qq(<p><font size="5">$The_Count recipes found.</font></p>); #Print count.
}
else
{
    print "<li>No Terms Specified</li>";
}

end_of_html($search_url, $title_url, $title, $terms, $bool, $case);
#...Remainder of the script follows, unchanged

I hope that does the trick, because I find this script difficult to test.

d5e5 109 Master Poster

If you want to use PHP to create a string containing a SELECT query containing both values in a $day_result array, you could do it like this:

<?php
$day_result = array(1, 4); // Initial array of numbers
$sql3 = "Select * from Venue where ";

foreach($day_result as $day_num){
    $dr[] = "idVenue != $day_num "; // Build array of strings
}

$sql3 .= implode(' AND ', $dr); // convert to string joined by ' AND ' and add to end of $sql3

echo $sql3;
?>
d5e5 109 Master Poster

opendir(FOLD, @fld); First error I see is that opendir expects an expression naming one directory. Any variable starting with @ contains an array whereas opendir needs a string representing the name of one directory only.

d5e5 109 Master Poster

That's great. I didn't think of that (Getopt:Long version.) Please mark this thread solved (even though it was you that solved it. :))

d5e5 109 Master Poster

If the OP had enabled warnings, and named the script something other than a number, then the following warning would have been helpful:
Argument "/home/david/Programming/Perl/weird.pl" isn't numeric in array element at /home/david/Programming/Perl/weird.pl line [whatever].

d5e5 109 Master Poster

I'm not sure I understand doubts number 1 and 2. You say that GetOptions ('d:s{,}' => \@dir, 'f:s{,}' => \@fil); doesn't compile? The following works for me.

#!/usr/bin/perl
#getopt01.pl
use strict;
use warnings;

use Getopt::Long;
my (@dir, @fil);

#-- prints usage if there is an unknown parameter

usage() if ( ! GetOptions('d:s{,}' => \@dir, 'f:s{,}' => \@fil));
            
if (@dir > 0){
    print "\n-d option specified with the following values:\n"
        . join("\n", @dir), "\n\n";
}

if (@dir > 0){
    print "-f option specified with the following values:\n"
        . join("\n", @fil), "\n\n";
}

print "My perl version is: $]\n";
sub usage
{
  print "Unknown option: @_\n" if ( @_ );
  print "usage: program [-d DIRECTORY_NAME [DIRECTORY_NAME]...] [-f FILE_NAME [FILE_NAME]...]\n";
  exit;
}

Running the above on the command line:

$ perl getopt02.pl -d /home /etc -f note.txt appointments.txt list.com

-d option specified with the following values:
/home
/etc

-f option specified with the following values:
note.txt
appointments.txt
list.com

My perl version is: 5.010000
d5e5 109 Master Poster

You could alter your SELECT statement to explicitly name the columns you want in your result set (instead of *) and include a calculated column which you would specify something like this:

SELECT order.item_name, order.quantity, item.price, order.quantity*item.price AS value 
FROM fb.order
LEFT JOIN item  on
	order.item_name = item.item_name
WHERE fb.order.order_status = 'Served' and tab_name='A'

(But then in PHP you would need to accumulate the value for each row in a variable to get your total value.)

BTW maybe it's not a good idea to name your table 'order' because it is a MySQL reserved word.

d5e5 109 Master Poster

Regarding doubt #3, I think you would have to write conditional logic to allow the -r (rename) parameter only if the -d (directory) parameter is specified. Maybe roughly like the following:

#!/usr/bin/perl
#getopt01.pl
use strict;
use warnings;

use Getopt::Long;
 
my ($help, @dir, @rename_to);
 
#-- prints usage if there is an unknown
#   parameter or help option is passed
usage() if ( ! GetOptions('help|?' => \$help, 'd:s' => \@dir, 'r:s' => \@rename_to)
         or defined $help );

if (@rename_to > 0 and @dir < 1){
    die "-r option specified without -d option.\n"
        . "If -d not specified, -r is not allowed.\n"
        . "If you don't eat your meat, you can't have any pudding!\n"
}

sub usage
{
  print "Unknown option: @_\n" if ( @_ );
  print "usage: program [-d DIRECTORY_NAME] [-r NEW_DIRECTORY_NAME] [--help|-?]\n";
  exit;
}
d5e5 109 Master Poster

That solution is slightly more efficient than mine, although I'm not sure it matters much in such a fast-completing script :)

Yes, I agree, if the OP is using this in a larger project, printing ten even numbers is not going to be one of the bottlenecks.

I just skimmed through an article that has a gripping title -- Optimization: Your Worst Enemy -- explaining why programmers should optimise only when necessary to solve performance problems.

d5e5 109 Master Poster

Have you looked at the one on http://dennismueller.org/blog/2009/03/csv-to-vcard-conversion-tool/? You don't have to use it online. He also gives a link from which you can download the source and run it locally. I tried downloading and extracting it. On my Linux platform I had to change the permissions for the folder where I extracted the files to give Other permission to create and delete folders. After doing that it read the sample csv file and created a vcard that looked OK to me. Might be worth trying. It's free.

d5e5 109 Master Poster

It's good to show one of the loop solutions too, as you did, since the OP said he was new to Perl. When I started with Perl, solutions using the map function seemed hard to read. This was the first time I found a good use for map so of course I wanted to show it off.:)

But using a loop can be easier to understand. Here's a minor variation on the loop approach.

#!/usr/bin/perl
use strict;
use warnings;

for (my $n = 2; $n < 21; $n += 2){
    print "$n\n";
}
d5e5 109 Master Poster

Maybe the PHP configuration on the server running your script tells PHP not to display any errors (although I don't see any errors in your script.) Try adding the following line to the beginning of your script: ini_set('display_errors', 1); http://www.wallpaperama.com/forums/how-to-display-php-errors-in-my-script-code-when-display-errors-is-disabled-t453.html

d5e5 109 Master Poster

Nice one, mitchems. Another way would be

#!/usr/bin/perl
use strict;
use warnings;

my @evens;
my $n = 0;
my $number_to_give_up_at = 100;
# $#evens will contain value of index of last element in @evens array
while ($n++ < $number_to_give_up_at and $#evens < 9){
    push @evens, $n if $n % 2 == 0;
}
print join("\n", @evens);

Spakes, please mark it solved so we can stop working on this.

d5e5 109 Master Poster

You're welcome. To understand how that works you need to know the shortcut for building a range of numbers, (lowest number followed by two dots followed by largest number, all within parentheses) which results in an array of sequential numbers, in increments of one. Plus you need to know the map function, which performs whatever function or statement you specify on each member of the array or list you specify.

There are other ways of doing the same thing, such as using some kind of loop.

d5e5 109 Master Poster

Maybe something like this?

<?php
$url = "http://localhost/temp-hum-light.html";
$str = file_get_contents($url);

if (preg_match('/(?:uN703610TF:\s*(\d+\.\d*))/', $str, $matches)) {
    $temp = $matches[1];
}

if (preg_match('/HU:\s*(\d+\.\d*)/', $str, $matches)) {
    $hum = $matches[1];
}

if (preg_match('/IL:\s*(\d+\.\d*)/', $str, $matches)) {
    $light = $matches[1];
}

echo '$temp is ' . "$temp\n";
echo '$hum is ' . "$hum\n";
echo '$light is ' . "$light\n";
?>
d5e5 109 Master Poster

Hi ,

How do I write a code that will print the first 10 even numbers in PERL

Thank you

Here is one way:

#!/usr/bin/perl
use strict;
use warnings;
map {print $_ * 2 . "\n"} (1..10);
d5e5 109 Master Poster
#!/usr/bin/perl
use strict;
use warnings;

my $index;
my $data5 = 'whatever';

#Because no value has yet been assigned to $index->{ $data5 }
# $index->{ $data5 } is currently uninitialized

$index->{ $data5 } = $index->{ $data5 }+1 ;
print '$index->{ $data5 } is equal to ' . "$index->{ $data5 }\n";

#Outputs the following:
#$index->{ $data5 } is equal to 1
#Use of uninitialized value in addition (+) at /home/david/Programming/Perl/temp.pl line 8.
d5e5 109 Master Poster

I am doing this project myself and have created this database so yes I do have the right to delete the user. But I have A BIGGER problem I need to backup the database I created and don't know how. Does anyone know how to back up my ijdb?

At the shell prompt mysqldump -u david -p daniweb > dw.sql It will prompt you for your password and when you enter it your database (mine is called 'daniweb') will be backed up into dw.sql, or whatever you want to call your backup file. The contents of the backup file will contain all the SQL commands to create the tables and insert all the data, etc. You can view it with any text editor.

d5e5 109 Master Poster
mysql> GRANT SELECT ON daniweb.people TO jess@localhost IDENTIFIED BY "jessrules";
Query OK, 0 rows affected (0.00 sec)

mysql> select User from mysql.user;
+------------------+
| User             |
+------------------+
| root             | 
| root             | 
| david            | 
| debian-sys-maint | 
| jess             | 
| root             | 
+------------------+
6 rows in set (0.00 sec)

mysql> DELETE FROM mysql.user where User = 'jess';
Query OK, 1 row affected (0.00 sec)

mysql> select User from mysql.user;
+------------------+
| User             |
+------------------+
| root             | 
| root             | 
| david            | 
| debian-sys-maint | 
| root             | 
+------------------+
5 rows in set (0.00 sec)

mysql>
d5e5 109 Master Poster

Are you sure $contents contains the string you say it does? When I manually assign the string you want to match to $contents the match works and there is something in the $out array.

<?php
$contents = <<<END
<a href="./viewtopic.php?f=15&amp;t=119871" class="topictitle">Twilight Graphic Novel</a>
END;
preg_match_all("/<a href=\".\/(viewtopic.php\?f=15&amp;t=[0-9]+)\" class=\"topictitle\">([#\w\s_\-!$%&()?.,'\":;{}\/\\|’=\[\]+\–\™ ]+)<\/a>/i",$contents,$out);

$len=count($out[0]);
echo '$len is equal to ' . "$len\n";
print_r($out);

//Gives the following output:
//$len is equal to 1
//Array
//(
//    [0] => Array
//        (
//            [0] => <a href="./viewtopic.php?f=15&amp;t=119871" class="topictitle">Twilight Graphic Novel</a>
//        )
//
//    [1] => Array
//        (
//            [0] => viewtopic.php?f=15&amp;t=119871
//        )
//
//    [2] => Array
//        (
//            [0] => Twilight Graphic Novel
//        )
//
//)
?>
d5e5 109 Master Poster

Ok, I have got the variables counting, but now I am having trouble sorting them.
I have looked at numerous tutorial websites and keep getting the same method but when I do implement it does not work. It is not giving an error, just not printing anything to screen,

#!/usr/bin/perl
    #use strict;
    #use warnings;
    #use Text::CSV;
   
my $dat_file = 'file.csv';
 my $index = {};
  my $index_test = {};
@data =('col1', 'col2', 'col3', 'col4', 'col5', 'col6', 'col7');

open (F, $dat_file), print "File Opened\n\n" || die ("Could not open file");


while ($line = <F>)
  {


    ($data1,$data2,$data3,$data4,$data5,$data6) = split ',', $line;

if (exists($index{$data3}))
{
  $index->{ $data3 } = 1;

}
else
{
    $index->{ $data3 } =$index->{ $data3 }+1 ;

}

if (exists($index{$data5}))
{
  $index->{ $data5 } = 1;

}
else
{
    $index->{ $data5 } = $index->{ $data5 }+1 ;

}


}

foreach $value (sort {$index{$a} cmp $index{$b} }
          	keys %index)
{
     print "$value =>			$index{$value}\n";
}

  close (F);
 
  print"\n";

This is the code I have, Its the parts at the end where I am trying to sort and print the list to screen but it displays nothing.

Can anyone see what might be wrong with this?

Thanks in advance.

N

You said earlier "I want to count how many times each unique entry is in either of these columns [columns 3 and 5]." I don't see how your code is supposed to accomplish this. You don't need to test if the value exists (i.e. has already been counted and saved in your hash) …

d5e5 109 Master Poster

I need some help. I have figured out most of my script but I need to search a string and see if it starts with certain characters and Does not end in another.

[$line1 = "EB*1**96" #should produce true value and blank line]
[if ($line1 =~ /^EB\*/ and $line1 ne /Y$/) {$line1 = "";}]
[print $line1]

Should print blank line or nothing

[$line1 = "EB*1**96*Y" #should produce False ]
[if ($line1 =~ /^EB\*/ and $line1 ne /Y$/) {$line1 = "";}]
[print $line1]

Should print EB*1**96*Y

I need to blank the line if it starts with EB* and the string does not end in Y


Any help would be appreaciated

#!/usr/bin/perl
#
use strict;
use warnings;

my $line1 = "EB*1**96";
my $line2 = "EB*1**96*Y";

#If string starts with EB and ends with any character other than Y
# then delete the string.

$line1 =~ s/^EB.*[^Y]$//;
$line2 =~ s/^EB.*[^Y]$//;

print '$line1 is ' . "$line1 \n";
print '$line2 is ' . "$line2 \n";
d5e5 109 Master Poster

Nice post. I agree with the above. In addition I always use a normal autoinc key, next to the customer's required id. At least then you can keep track of overflows, and your keys won't fail.

That makes a lot of sense. Give the customer the field they want. I don't remember who told me that a good key should NOT have meaning, but I think this was what they were getting at. The customer wants a patient id that means something to them such as "date of admission and this was the nth patient admitted that day." Fine. Provide that. But the real key should be something that doesn't prevent adding new patients even in unlikely situations (such as another hospital merges with this one and thousands of patients need to be added to your database.)

d5e5 109 Master Poster

Are you quite sure the hospital will never have to admit more than 999 new patients during a single day, at least not until you have retired?:)

You could create another table to store the last patient id used. Add only one row to this table. Whenever a row is inserted into your patient table, a trigger function could update the single row in your last-patient-id table. This function would compare the date portion of the last patient id to determine if it represents the current date. If so, increment the numeric suffix of that id. If not, update the id to current date followed by the reinitialised numeric suffix. (Or the date portion and numeric suffix could be in two separate columns in your last-patient-id table, if that's easier.)

I haven't written trigger functions in MySQL yet, so am not certain but fairly sure you can write one to do that.

A similar question is discussed at https://www.scriptcase.net/forum_en_us/index.php?topic=1339.0

d5e5 109 Master Poster

Thanks for your help.

The columns I put in was just for demonstration. Really it will be read from a comma delimited file (column 3 and 5) But apart from that its what i'm looking for?

Is there much other adjustment?

No other adjustment that I'm aware of. You already know how to split on something other than space and save the desired columns into scalar variables. For very simple CSV data like your example split works OK, but for more complex data that you'll have to handle some day you'll be better off using a module that parses the CSV into columns for you. As masijade already pointed out, time invested in learning how to use Text::CSV; or one of the other csv parser modules will pay off if you ever have to deal with column values like 1,302 or "eats, shoots, and leaves" that have embedded commas that you do NOT want to split on.

d5e5 109 Master Poster

Using the sample data you provided that has two columns delimited by a space, running the following script:

#!/usr/bin/perl
use strict;
use warnings;

*ARGV = *DATA if scalar(@ARGV) == 0;

my %count; #Hash containing count of occurences of each unique value

while (<>) {
    my ($col_x_val, $col_y_val) = split; #splits record by space (default delimiter) 
    $count{$col_x_val}++;#Increment count if found in column 'x'
    $count{$col_y_val}++;#Increment count if found in column 'y'
}

foreach (sort how_to_sort keys %count){
    print "$_ occurs $count{$_} times.\n";
}

sub how_to_sort{ #Specify numeric sort by counted value in descending order
    $count{$b} <=> $count{$a};
}
__DATA__
1 6
2 4
1 2
2 1
3 8
4 9
5 3
3 1
5 6
6 6
6 6
4 3
6 4
6 4
6 4
6 5
6 6
6 8
6 1
6 9

gives the following output:

6 occurs 15 times.
4 occurs 6 times.
1 occurs 5 times.
3 occurs 4 times.
2 occurs 3 times.
5 occurs 3 times.
8 occurs 2 times.
9 occurs 2 times.
d5e5 109 Master Poster

The following reads each line from an input file, removes the specified pattern from each line, if found, and prints each line to standard output, which could easily be redirected to a file.

#!/usr/bin/perl
use strict;
use warnings;

*ARGV = *DATA if scalar(@ARGV) == 0;

while (<>) {
    s/<HTML>//g;
    print;}

__DATA__
Hello there.
The words here at the end of the script
supply default testing data in case there
is no input file named on the command line.
If you want to delete all occcurences of <HTML> and <HTML> and <HTML>
then this should do it, but what about the </HTML> tag?
The </HTML> won't get deleted but the <HTML> tag will.
Is that what you want?
d5e5 109 Master Poster

Is it too late to change the design of the 'children' table? Your problem comes from there.

Why not have only two columns? One column would identify the user and the other the name of one child. Each user could have as many rows in the children table as needed to identify all that user's children. If you must enforce a maximum of four children per user you could do that in your program logic. But a one-many relation between the user table and the children table would give you more flexibility than your actual design, in my opinion.

d5e5 109 Master Poster

Apparently, part of the problem starts at this statement: @arr=split("",$_); #This splits the string into single characters To test, I ran the following:

print join("\n",split("",'abcdefghijklmno'));

And the output was

a
b
c
d
e
f
g
h
i
j
k
l
m
n
o

I know that doesn't help much. If nobody else figures out how to do it, I'll have another look when there's time.

d5e5 109 Master Poster

Here is an example of how to find differences between an older and newer file, using a hash. For simplicity I used ordinary text data, but it should work for csv files as well since you don't need to parse the lines into fields at this point. (You can parse the data with another script, later.)

I attached the data files, 'names_1.txt' and 'names_2.txt' to this post.

#!/usr/bin/perl
#print_diffs.pl
use strict;
use warnings;

my $dir = '/home/david/Programming/Perl/data';
my $f1 = "$dir/names_1.txt";
my $f2 = "$dir/names_2.txt";
open FILE1, "$f1" or die "Could not open $f1: $! \n";

my %results = ();#Hash to store lines from files
my %meaning = (-1, "In new file but not in old file",
               0, "In both new and old files",
               1, "In old file but not in new file",); #Hash associating values with statuses

while(my $line = <FILE1>){
    chomp $line;
    $results{$line}=1;
}
close(FILE1);

open FILE2, "$f2" or die "Could not open $f2: $! \n";
while(my $line =<FILE2>) {
    chomp $line;
    #$results{$line}++; #Instead of incrementing by one...
    $results{$line}--; #Instead of incrementing by one...
}
close(FILE2);

foreach(sort order keys %results){
    print "Key $_ has value $results{$_} which means $meaning{$results{$_}}\n";
}

sub order{
    $results{$a} <=> $results{$b};
}
d5e5 109 Master Poster

I pasted some text into the __DATA__ section at the end of my script for convenience but the following will work just as well if you read from a real text file.

#!/usr/bin/perl
#TestForAsterisks.pl
use strict;
use warnings;

sub is_separator {
    my $line = shift; #Assign passed argument to variable
    if ($line =~ m{^\/\/(\*)+}) {
        return 1; #Return true value
    }
    else{
        return 0; #Return false value
    }
}

while (<DATA>){
    if (is_separator($_)){
        print "Line number $. is a separator.\n";
    }else{
        print "Line number $. is not a separator.\n";
    }
}
__DATA__
Last year, I was based in Sidney while exploring the surrounding Saanich Peninsula’s emerging foodie culture — nascent vineyards and cideries, family enterprises making handcrafted gin and raw chocolate. But I was also pleasantly surprised to discover Sidney’s other angle: Inspired by Hay-on-Wye, the medieval Welsh town known for its many secondhand and antiquarian bookstores, Sidney,  population 11,000, is a bibliophile’s paradise — with no fewer than 12 independent specialty bookstores. There are rare, collectible and bargain books, with topics ranging from military history to gardening. And, yes, there are enough Stieg Larssons to go around.
//*********************************************
Since then, I have been wanting to return and get lost in these shops, perhaps even discuss a book or two over oyster burgers with some literary pals.
Indeed, Sidney seemed like the perfect place for a book club getaway. There is a new hotel, the Sidney Pier, a sleek seaside property with a restaurant that serves inspired local food …