#/bin/bash
sort(){
for ((i = 0; i<$n; i++))
do
for((j = 0; j<`expr $n - $i - 1`; j++))
do
if [ ${arrival_time[j]} -gt ${arrival_time[$((j+1))]} ]
then
# swap
temp=${arrival_time[j]}
arrival_time[$j]=${arrival_time[$((j+1))]}
arrival_time[$((j+1))]=$temp
temp=${burst_time[j]}
burst_time[$j]=${burst_time[$((j+1))]}
burst_time[$((j+1))]=$temp
temp=${pid[j]}
pid[$j]=${pid[$((j+1))]}
pid[$((j+1))]=$temp
elif [ ${arrival_time[j]} -eq ${arrival_time[$((j+1))]} ]
then
if [ ${pid[j]} -eq ${pid[$((j+1))]} ]
then
temp=${arrival_time[j]}
arrival_time[$j]=${arrival_time[$((j+1))]}
arrival_time[$((j+1))]=$temp
temp=${burst_time[j]}
burst_time[$j]=${burst_time[$((j+1))]}
burst_time[$((j+1))]=$temp
temp=${pid[j]}
pid[$j]=${pid[$((j+1))]}
pid[$((j+1))]=$temp
fi
fi
done
done
}
border(){
z=121
for ((i=0; i<$z; i++))
do
echo -n "-"
done
echo ""
}
findWaitingTime(){
service_time[0]=0
waiting_time[0]=0
for ((i=1; i<$n; i++))
do
z=1
y=`expr $i - $z`
service_time[$i]=`expr ${service_time[$y]} + ${burst_time[$y]} `
waiting_time[$i]=`expr ${service_time[$i]} - ${arrival_time[$i]}`
if [ ${waiting_time[$i]} -lt 0 ]
then
waiting_time[$i]=0
fi
done
}
findTurnAroundTime(){
for ((i=0; i<$n; i++))
do
tat[$i]=`expr ${waiting_time[$i]} + ${burst_time[$i]}`
done
}
findAverageTime(){
sort
findWaitingTime
findTurnAroundTime
total_wt=0
total_tat=0
border
printf "|%-18s|%-20s|%-18s|%-20s|%-18s|%-20s|\n" "Process Id" "Burst time" "Arrival time" "Waiting time" "Turn around time" "Completion time"
border
for ((i=0; i<$n; i++))
do
total_wt=`expr $total_wt + ${waiting_time[$i]}`
total_tat=`expr ${tat[$i]} + $total_tat`
completion_time=`expr ${arrival_time[$i]} + ${tat[$i]}`
printf "|%-18s|%-20s|%-18s|%-20s|%-18s|%-20s|\n" ${pid[$i]} ${burst_time[$i]} ${arrival_time[$i]} ${waiting_time[$i]} ${tat[$i]} $completion_time
#echo "${burst_time[$i]} ${arrival_time[$i]} ${waiting_time[$i]} ${tat[$i]} $completion_time"
done
border
#avgwt=`echo "scale=3; $total_wt / $n" | bc`
echo -n "Average waiting time ="
printf %.3f\\n "$(($total_wt / $n))"
#avgtat=`echo "scale=3; $total_tat / $n" | bc`
echo -n "Average turn around time ="
printf %.3f\\n "$(($total_tat / $n))"
for ((i=0; i<8*n+n+1; i++))
do
echo -n "-"
done
echo ""
for ((i=0; i<$n; i++))
do
echo -n "| "
echo -n "P${pid[$i]}"
echo -n " "
done
echo "|"
for ((i=0; i<8*n+n+1; i++))
do
echo -n "-"
done
echo ""
echo -n "0 "
for ((i=0; i<$n; i++))
do
echo -n "`expr ${arrival_time[$i]} + ${tat[$i]}`"
echo -n " "
done
echo ""
}
n=$(sed -e '1~2d' fcfs1.txt |awk '{ for (i=1; i<=NF; i++) RtoC[i]= (i in RtoC?RtoC[i] OFS :"") $i; } END{ for (i=1; i<=NF; i++) print RtoC[i] }'| awk '{print $1}' |wc -l)
for ((i=0; i<$n; i++))
do
pid[$i]=$(cat fcfs.txt | awk '{print $1}')
arrival_time[$i]=$(cat fcfs.txt | awk '{print $2}')
burst_time[$i]=$(cat fcfs.txt | awk '{print $3}')
done
findAverageTime
fcfs.txtの内容は次のとおりです。
1 15 10
2 17 12
入力ファイルにプロセスが1つしかない場合、スクリプトは正常に機能し、複数のプロセスがあるときに入力ファイルにプロセスが1つしかない場合、スクリプトはエラー出力を提供します。
-------------------------------------------------------------------------------------------------------------------------
|Process Id |Burst time |Arrival time |Waiting time |Turn around time |Completion time |
-------------------------------------------------------------------------------------------------------------------------
|1 |5 |10 |0 |5 |15 |
-------------------------------------------------------------------------------------------------------------------------
Average waiting time =0.000
Average turn around time =5.000
----------
| P1 |
----------
0 15
答え1
テキスト操作のためのより良い言語を学ぶ必要がある理由を示すために、Perlを使用して簡単に実行できるタスクの例は次のとおりです。元のシェルスクリプトには約128行のコードがあるようですが、動作しません(または動作方法を説明するコメントがあります)。このPerlスクリプトの長さは約57行です(コメントは約30行を除く)。
各行の正しい計算を見つけるために最善を尽くしましたが、いくつかの間違いをした可能性があります。スクリプトが過度に複雑で(非常に)反復的で何をしているのか、なぜ何をするのか理解しにくいです。 。以下のスクリプトを自由に修正するか、正しい計算が何であるかを教えてください。
$ cat summarise_fcfs.pl
#!/usr/bin/perl
use strict;
# Construct the format string for printf. and the ruler line too.
# Width of each field is just enough to fit its header plus a space on
# both sides.
#my @headers = ("Process ID", "Burst time", "Arrival time",
# "Waiting time", "Turn around time", "Completion time");
# Shorter headers to fit in "standard" 80-column terminal
my @headers = ("Process ID", "Burst", "Arrival", "Waiting", "Turnaround", "Completion");
my $fmt = '|'; my $ruler = '|';
foreach (@headers) {
my $len = length($_);
$fmt .= " %${len}s |";
$ruler .= '-' x ($len + 2) . '|';
};
$fmt .= "\n"; $ruler .= "\n";
my $total_wait = 0;
my $total_tat = 0;
# @data is an Array-of-Arrays (AoA) data structure to hold the values
# for each PID. Also known as a List-of-Lists or LoL. See `man
# perllol` and `man perldsc` for details.
my @data = ();
# @st is a single-dimensional array to hold the service time values
# for each PID. These aren't going to be printed with the printf
# format string, so are kept separately from @data (it's easier than
# extracting an array slice from @data to print for each row)
my @st = ();
# Record counter
my $i = 0;
while(<>) {
chomp;
s/^\s*|\s*$//g; # strip leading and trailing whitespace
s/#.*//; # strip comments if any
next if /^\s*$/; # skip empty lines
my ($pid, $arrival, $burst) = split;
my $st = 0;
if ($i > 0) {
# previous st + previous burst
$st = $st[$i-1] + $data[$i-1][1]
};
my $wait = $st - $arrival;
$wait = 0 if ($wait < 0);
my $tat = $wait + $burst;
my $completion = $arrival + $tat;
# Store the data for the current PID in the @data AoA.
$data[$i] = [ $pid, $burst, $arrival, $wait, $tat, $completion ];
# and store the service time too
$st[$i] = $st;
# keep track of totals and increment the record counter.
$total_wait += $wait;
$total_tat += $tat;
$i++;
};
# All data has been read and processed, now it's time
# to produce some output.
print $ruler, sprintf($fmt, @headers), $ruler;
# sort by arrival time (element 2 of each array in
# @data). Like bash, perl array indices start from zero.
foreach my $row (sort { $data[$a][2] <=> $data[$b][2] } keys @data) {
printf $fmt, @{ $data[$row] };
};
print $ruler, "\n";
printf "Average waiting time = %.3f\n", $total_wait / $i;
printf "Average turn around time = %.3f\n\n", $total_tat / $i;
# Now print a table of completion times (5th element of @data[$row])
# for each PID. Limit to 8 columns (PIDs) per output line so it
# doesn't get ridiculously wide.
my $step = 8; # max number of PIDs per output row
for (my $start_col = 0; $start_col < $i ; $start_col += $step) {
my $end_col = $start_col + $step - 1;
$end_col = $i-1 if $end_col > $i;
# Rebuild headers and ruler line for each $step number of PIDs
my @P_headers = map { "P" . $data[$_][0] } $start_col..$end_col;
my $P_fmt = '|'; my $P_ruler = '|';
foreach (@P_headers) {
#my $len = length($_)+4;
my $len = 6; # is 6 characters enough for the PID?
$P_fmt .= " %${len}s |";
$P_ruler .= '-' x ($len + 2) . '|';
};
$P_fmt .= "\n"; $P_ruler .= "\n";
# and print the current row
print $P_ruler, sprintf($P_fmt, @P_headers), $P_ruler;
printf $P_fmt, map { $data[$_][5] } $start_col..$end_col;
print $P_ruler, "\n";
}
出力例:
$ ./summarise_fcfs.pl fcfs.txt
|------------|-------|---------|---------|------------|------------|
| Process ID | Burst | Arrival | Waiting | Turnaround | Completion |
|------------|-------|---------|---------|------------|------------|
| 1 | 10 | 15 | 0 | 10 | 25 |
| 2 | 12 | 17 | 0 | 12 | 29 |
|------------|-------|---------|---------|------------|------------|
Average waiting time = 0.000
Average turn around time = 11.000
|--------|--------|
| P1 | P2 |
|--------|--------|
| 25 | 29 |
|--------|--------|