bashスクリプトを使用して先着順を作成する[閉じる]

bashスクリプトを使用して先着順を作成する[閉じる]
#/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 |
|--------|--------|

関連情報