0

私は bash から始めていますが、この例を理解したいと思っています... "to_roman" 関数を理解するのを手伝ってくれる人がいれば、とても感謝しています! または、ヘルプ用のドキュメントがある場合は、ありがとう!

#!/bin/bash
LIMIT=200
E_ARG_ERR=65
E_OUT_OF_RANGE=66

if [ -z "$1" ]
then
  echo "Usage: `basename $0` number-to-convert"
  exit $E_ARG_ERR
fi  

num=$1
if [ "$num" -gt $LIMIT ]
then
    echo "Out of range!"
    exit $E_OUT_OF_RANGE
fi  

to_roman ()
{
    number=$1
    factor=$2
    rchar=$3
    let "remainder = number - factor"
    while [ "$remainder" -ge 0 ]
    do
        echo -n $rchar
        let "number -= factor"
        let "remainder = number - factor"
    done  
    return $number
}

to_roman $num 100 C
num=$?
to_roman $num 90 LXXXX
num=$?
to_roman $num 50 L
num=$?
to_roman $num 40 XL
num=$?
to_roman $num 10 X
num=$?
to_roman $num 9 IX
num=$?
to_roman $num 5 V
num=$?
to_roman $num 4 IV
num=$?
to_roman $num 1 I
echo
exit
4

3 に答える 3

1

to_roman ()関数定義であり、プログラム自体の一部ではありません。実際のプログラムはその下から始まります。

の前to_roman ()に、プログラムは単に入力を検証しています。パラメータを含めましたか?そうでない場合は、最初のifステートメントがそれをキャッチします。

数は 200 を超えていますか? 200 より大きい場合は、2 番目ifが処理します。

プログラムの核心は次のとおりです。

to_roman $num 100 C
num=$?
to_roman $num 90 LXXXX
num=$?
to_roman $num 50 L
num=$?

プログラムはto_roman、3 つのパラメーターを使用して関数を実行しています。1 つ目は変換したい数値 (またはその数値の残り) です。2 つ目はその数値の係数で、3 つ目は出力する文字です。

プログラムは、ループを使用しています。たとえば、パラメータ175100、およびCto_roman関数に渡すと、 が減算され150 - 100、結果がまだ 0 より大きいことがわかり、文字が出力されてC再試行されます。この場合、もう一度試行しますが、番号を取得します-25。ゼロ未満なので、サブルーチンは で終了し75ます。残り物(この場合は金額)のnum=$?セット。number75

これは(は 0 より小さいto_roman 75 90 LXXXXため何も表示されません)、 ( 75 から1 を引くことができるため1 を表示します) に対して行われます。その最後の結果は です。90 - 75to_roman 75 50 LL5025

シェル スクリプトを理解するためにできることを次に示します。初め:

$ export PS4="\$LINENO: "

PS4プロンプトはデバッグです。デフォルトのPS4プロンプトは+あまり役に立ちません。これにより、PS4デバッグ中のシェル スクリプトの行番号にプロンプ​​トが変更されます。

ここで、デバッグしようとしているシェル スクリプトの領域を配置set -xvします。set +xvこの場合、スクリプトの最初と最後に配置することをお勧めします。番号 175 のデバッグ出力を次に示します。何が起こっているかを確認してください。

$ ./roman.sh 175
LIMIT=200
3: LIMIT=200
E_ARG_ERR=65
4: E_ARG_ERR=65
E_OUT_OF_RANGE=66
5: E_OUT_OF_RANGE=66

if [ -z "$1" ]
then
  echo "Usage: `basename $0` number-to-convert"
  exit $E_ARG_ERR
fi  
7: '[' -z 175 ']'

num=$1
13: num=175
if [ "$num" -gt $LIMIT ]
then
    echo "Out of range!"
    exit $E_OUT_OF_RANGE
fi  
14: '[' 175 -gt 200 ']'

to_roman ()
{
    number=$1
    factor=$2
    rchar=$3
    let "remainder = number - factor"
    while [ "$remainder" -ge 0 ]
    do
        echo -n $rchar
        let "number -= factor"
        let "remainder = number - factor"
    done  
    return $number
}

to_roman $num 100 C
35: to_roman 175 100 C
22: number=175
23: factor=100
24: rchar=C
25: let 'remainder = number - factor'
26: '[' 75 -ge 0 ']'
28: echo -n C
C29: let 'number -= factor'
30: let 'remainder = number - factor'
26: '[' -25 -ge 0 ']'
32: return 75
num=$?
36: num=75
to_roman $num 90 LXXXX
37: to_roman 75 90 LXXXX
22: number=75
23: factor=90
24: rchar=LXXXX
25: let 'remainder = number - factor'
26: '[' -15 -ge 0 ']'
32: return 75
num=$?
38: num=75
to_roman $num 50 L
39: to_roman 75 50 L
22: number=75
23: factor=50
24: rchar=L
25: let 'remainder = number - factor'
26: '[' 25 -ge 0 ']'
28: echo -n L
L29: let 'number -= factor'
30: let 'remainder = number - factor'
26: '[' -25 -ge 0 ']'
32: return 25
num=$?
40: num=25
to_roman $num 40 XL
41: to_roman 25 40 XL
22: number=25
23: factor=40
24: rchar=XL
25: let 'remainder = number - factor'
26: '[' -15 -ge 0 ']'
32: return 25
num=$?
42: num=25
to_roman $num 10 X
43: to_roman 25 10 X
22: number=25
23: factor=10
24: rchar=X
25: let 'remainder = number - factor'
26: '[' 15 -ge 0 ']'
28: echo -n X
X29: let 'number -= factor'
30: let 'remainder = number - factor'
26: '[' 5 -ge 0 ']'
28: echo -n X
X29: let 'number -= factor'
30: let 'remainder = number - factor'
26: '[' -5 -ge 0 ']'
32: return 5
num=$?
44: num=5
to_roman $num 9 IX
45: to_roman 5 9 IX
22: number=5
23: factor=9
24: rchar=IX
25: let 'remainder = number - factor'
26: '[' -4 -ge 0 ']'
32: return 5
num=$?
46: num=5
to_roman $num 5 V
47: to_roman 5 5 V
22: number=5
23: factor=5
24: rchar=V
25: let 'remainder = number - factor'
26: '[' 0 -ge 0 ']'
28: echo -n V
V29: let 'number -= factor'
30: let 'remainder = number - factor'
26: '[' -5 -ge 0 ']'
32: return 0
num=$?
48: num=0
to_roman $num 4 IV
49: to_roman 0 4 IV
22: number=0
23: factor=4
24: rchar=IV
25: let 'remainder = number - factor'
26: '[' -4 -ge 0 ']'
32: return 0
num=$?
50: num=0
to_roman $num 1 I
51: to_roman 0 1 I
22: number=0
23: factor=1
24: rchar=I
25: let 'remainder = number - factor'
26: '[' -1 -ge 0 ']'
32: return 0
echo
52: echo

set -xv
53: set -xv
exit
54: exit
于 2013-10-27T17:40:29.900 に答える
0

to_roman()numberは、 、factor、およびの3 つのパラメータを取りますrchar。関数を定義した後、スクリプトが最初に行うことは、 (スクリプト自体への引数としてコマンドラインで渡された) の
引数で関数を呼び出すことです。$numスクリプトが処理できる最大係数: 100; およびその要素のローマ数字表現 (C)。
数値から係数を引いて余りを取得し、余りがゼロ以上の場合は、rchar (この場合は C) を出力し、出力したばかりの文字の値 (ここでは 100) を削除して数値を更新し、更新します。残り、繰り返します。
最初の数値が 100 未満の場合、最初の剰余の計算はゼロ未満になるため、何も出力されず、値も変化しません。
次に、スクリプトは 90 を処理します。 num=$?to_roman() への各呼び出しの間の in$numは、前の呼び出しの戻り値に設定されます。それがかなり明確
であることを願っています。

于 2013-10-27T15:57:04.683 に答える
0

単純に数値と「因子」および因子のローマ字表記を取り、単純にループして数値 mod(factor) のローマ字表記を吐き出します。

于 2013-10-27T14:24:24.877 に答える