I don't like the mix of shell and Perl in the code, but that's apparently for pedagogical reasons so we have to ignore it.
process_book_sold()
{
read -p "Title: " title
read -p "Author: " author
read -p "No Of Copies Sold : " cpySold
if [ -n "$title" -a -n "$author" ]; then
perl -ne '
BEGIN{ $title = shift; $author = shift; $sales = shift; }
@a = split /:/;
if ($a[0] =~ m/$title/i and $a[1] =~ m/$author/i)
{
print "Current Book Info:\n";
print "$a[0], $a[1], $a[2], $a[3], $a[4]\n";
$a[3] -= $sales;
$a[4] += $sales;
print "New Book Info:\n";
print "$a[0], $a[1], $a[2], $a[3], $a[4]\n";
}
END{ print "\n" }' "$title" "$author" "$cpySold" /home/student/Downloads/BookDB.txt
fi
}
Apart from renaming pattern
to title
and pattern1
to author
, this code passes the shell variable $cpySold
to the Perl. It also uses a simpler method of retrieving the first three arguments (simply capture the value from shift
). The split
is the same as before. It isn't entirely clear what the format in the data file is since the printed formats use commas rather than colons to separate the fields.
I simply want the values from new book info to replace current book info in the BookDB.txt
file.
I'm not convinced this is doing you any favours (you won't learn much unless you try doing it yourself), but ...
process_book_sold()
{
title="$1"
author="$2"
cpySold="$3"
if [ -n "$title" -a -n "$author" ]
then
perl -i -we '
use strict;
use English "-no_match_vars";
my $title = shift;
my $author = shift;
my $sales = shift;
while (<>)
{
chomp;
my @a = split /:/;
print STDERR "Debug: @a\n";
if ($a[0] =~ m/$title/i and $a[1] =~ m/$author/i)
{
print STDERR "Current Book Info:\n";
print STDERR "$a[0], $a[1], $a[2], $a[3], $a[4]\n";
$a[3] -= $sales;
$a[4] += $sales;
print STDERR "New Book Info:\n";
print STDERR "$a[0], $a[1], $a[2], $a[3], $a[4]\n";
$OFS = ":";
$ORS = "\n";
print @a;
}
}
' "$title" "$author" "$cpySold" BookDB.txt # /home/student/Downloads/BookDB.txt
fi
}
# read -p "Title: " title
# read -p "Author: " author
# read -p "No Of Copies Sold : " cpySold
process_book_sold "Alice in Wonderland" "Carroll" "3"
This doesn't pester me with typing the title, author or number of copies sold. You can reinstate those lines if you wish, but the function is probably more useful if it takes the arguments. (It is often good to separate user interaction from code that operates on files.) I've used the correct author name (unless you want to use Dodgson as the real name of the author who used the pseudonym Lewis Carroll). The Perl script uses the -i
option to overwrite the input files. It uses the English
module so it can set $OFS
and $ORS
. It writes debug information to STDERR (otherwise, it would be part of the information written to the file).
When the file was called pbs2.sh
, a sample run of the script looked like:
$ cat BookDB.txt; bash pbs2.sh; cat BookDB.txt
Alice in Wonderland:Carroll:$12.40:74:226
Debug: Alice in Wonderland Carroll $12.40 74 226
Current Book Info:
Alice in Wonderland, Carroll, $12.40, 74, 226
New Book Info:
Alice in Wonderland, Carroll, $12.40, 71, 229
Alice in Wonderland:Carroll:$12.40:71:229
$
Clearly, this wasn't the first time I'd run the script, and at times I used values other than 3 for the number of copies sold.
With explicit file management, you can write:
process_book_sold()
{
title="$1"
author="$2"
cpySold="$3"
if [ -n "$title" -a -n "$author" ]; then
perl -we '
use strict;
use English "-no_match_vars";
my $title = shift;
my $author = shift;
my $sales = shift;
my $file = shift;
open my $fh, "+<", $file or die "Failed to open file $file for reading and writing";
my $text;
{
local $/;
$text = <$fh>;
}
chomp $text;
my @a = split /:/, $text;
print "Debug: @a\n";
if ($a[0] =~ m/$title/i and $a[1] =~ m/$author/i)
{
print "Current Book Info:\n";
print "$a[0], $a[1], $a[2], $a[3], $a[4]\n";
$a[3] -= $sales;
$a[4] += $sales;
print "New Book Info:\n";
print "$a[0], $a[1], $a[2], $a[3], $a[4]\n";
seek $fh, 0, 0;
truncate $fh, 0;
$OFS = ":";
$ORS = "\n";
print $fh @a;
}
close $fh;
' "$title" "$author" "$cpySold" BookDB.txt # /home/student/Downloads/BookDB.txt
fi
}
# read -p "Title: " title
# read -p "Author: " author
# read -p "No Of Copies Sold : " cpySold
process_book_sold "Alice in Wonderland" "Carroll" "7"
Sample run:
$ cat BookDB.txt; bash pbs1.sh; cat BookDB.txt
Alice in Wonderland:Carroll:$12.40:50:250
Debug: Alice in Wonderland Carroll $12.40 50 250
Current Book Info:
Alice in Wonderland, Carroll, $12.40, 50, 250
New Book Info:
Alice in Wonderland, Carroll, $12.40, 43, 257
Alice in Wonderland:Carroll:$12.40:43:257
$