コードにシェルと 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
する以外に、このコードはシェル変数を Perl に渡します。また、最初の 3 つの引数を取得する簡単な方法も使用します (単純に から値を取得します)。は、以前と同じです。印刷された形式ではフィールドの区切りにコロンではなくコンマが使用されているため、データ ファイルの形式が完全には明確ではありません。title
pattern1
author
$cpySold
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"
これは、タイトル、著者、または販売部数を入力することで私を悩ませることはありません。必要に応じてこれらの行を元に戻すことができますが、関数は引数を取る方がおそらくより便利です。(ファイルを操作するコードからユーザーの操作を分離することは、しばしば良いことです。) 私は正しい作者名を使用しました (Lewis Carroll というペンネームを使用した作者の本名として Dodgson を使用したい場合を除きます)。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
$