我不喜欢在代码中混合使用 shell 和 Perl,但这显然是出于教学原因,所以我们不得不忽略它。
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
}
除了重命名pattern
totitle
和pattern1
to之外author
,此代码还将 shell 变量传递$cpySold
给 Perl。它还使用一种更简单的方法来检索前三个参数(只需从 中捕获值shift
)。和split
以前一样。数据文件中的格式是什么并不完全清楚,因为打印的格式使用逗号而不是冒号来分隔字段。
我只是希望新书信息中的值替换BookDB.txt
文件中的当前书信息。
我不相信这对你有任何好处(除非你自己尝试做,否则你不会学到很多东西),但是......
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"
这不会困扰我输入标题、作者或已售出的副本数量。如果您愿意,您可以恢复这些行,但如果该函数接受参数,它可能更有用。(将用户交互与操作文件的代码分开通常很好。)我使用了正确的作者姓名(除非您想使用 Dodgson 作为使用化名 Lewis Carroll 的作者的真实姓名)。Perl 脚本使用-i
选项来覆盖输入文件。它使用English
模块,因此它可以设置$OFS
和$ORS
。它将调试信息写入 STDERR(否则,它将是写入文件的信息的一部分)。
调用文件时pbs2.sh
,脚本的示例运行如下所示:
$ 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
$
显然,这不是我第一次运行该脚本,而且有时我使用 3 以外的值来表示已售出的副本数量。
通过显式文件管理,您可以编写:
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"
样品运行:
$ 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
$