2

私はこの気の利いた bash スクリプトに出くわしましたが、それは少し退屈です。

#!/bin/bash
function f() {
    sleep "$1"
    echo "$1"
}
while [ -n "$1" ]
do
    f "$1" &
    shift
done
wait

数値で指定された秒数スリープし、その数値を出力します。最小の数値が最初に起動します。

最初に数字をリスト内の最大数で割り、次にそれを実行し、終了時に最大値を掛けることで改善できると考えていました。

これが私の最初の試みです:

#!/bin/bash

declare -a to_sort

function f() {
    sleep "$1"
    final_var=$(echo "$1*$2"|bc)
    echo "$1"
}
function max(){
for var in "$@"
do
    if [ "$var" -gt "$max" ] # Using the test condition
    then
        max="$var"
    fi
done
}

echo "$1"| read -a to_sort

let max_var = max to_sort

for i in "${to_sort[@]}"
do
    parsed_var=$(echo "$i/$max_var"|bc)
    f parsed_var max_var &
    shift
done
wait

どこが間違っていますか?

4

3 に答える 3

6

以下にコメントされているように、これが機能しない原因となる構文とロジックに 7 つの問題がありました。

#!/bin/bash

declare -a to_sort

function f() {
    sleep "$1"
    final_var=$(echo "$1*$2"|bc)
    #Output result after multiplication
    #and skip decimals
    echo "${final_var%.*}"
}
function max(){
# Initialize max so we have something to compare against
max=$1
for var in "$@"
do
    if [ "$var" -gt "$max" ]
    then
        max="$var"
    fi
done
# output the max we found
echo $max
}

# Avoid assigning in subshells
read -a to_sort <<< "$1"
#This is how you assign the output of a command
max_var=$(max "${to_sort[@]}")

for i in "${to_sort[@]}"
do
    # Add scale to avoid truncating all to 0
    parsed_var=$(echo "scale=6; $i/$max_var"|bc)

    # expand variables
    f $parsed_var $max_var &
    shift
done
wait                            

また、GNU sleep は分数を処理しますが、他の多くの OS は処理しないことに注意してください。

于 2013-02-19T00:50:59.253 に答える
1

この行

echo "$1"| read -a to_sort

to_sortパイプラインの完了後に存在しなくなったサブシェルにの値を設定します。の値を設定しto_sortて後で使用できるようにreadするには、現在のシェルで実行するコマンドが必要です。1つの可能性:

read -a to_sort <<< "$1"
于 2013-02-18T22:56:09.337 に答える
1

@その他の人がすでに回答しているのを見ましたが、とにかくこれを投稿します... この
中のいくつかは、私の個人的なやり方です。
編集:コードに貼り付けるときにいくつかの行を忘れました

#!/usr/bin/env bash

# I have learned that the above is prefered over "#!/bin/bash",
# to be more portable I think.


# Do this here (instead of 'echo "$1"| read -a to_sort' below (which was
# wrong anyway) because you chose to use "for i in 'to_sort'" below
# you can't use 'shift' there so you must use all arguments already here.
declare -a to_sort=("$@")
#debug: declare -p to_sort

function f() {
  sleep "$1"

  # This can be done in another way, see below
  # (and "final_var" is not used anywhere else)
  #final_var=$(echo "$1*$2"|bc)
  final_var=$( bc <<< "$1 * $2" )
  #debug: echo "\$1:$1; \$2:$2; final_var:$final_var"

  echo "$1"
}

function max() {
  res=0
  for var in "$@"; do
    # Tip: use (( ... )) when testing numeric values, no need for "$" when
    # using that.
    #if [ "$var" -gt "$max" ] # Using the test condition
    if (( var > max )); then
      # You can't set a return value for the function, echo at the en instead
      #max="$var"
      res="$var"
    fi
  done
  echo "$res"
}

# This is wrong (as @chepner points out)
#echo "$1"| read -a to_sort
# if used here it should be 'to_sort[0]="$1"', when using like this
# there is no need to use "declare -a ..."

# This is wrong
#let max_var = max to_sort
# - no space before or after "="
# - not necessary to us "let"
# - can't assign directly from a function
# Should be
max_var=$(max "${to_sort[@]}")
#debug: echo "max_var:$max_var"

for i in "${to_sort[@]}"; do
  # This is wrong
  #parsed_var=$(echo "$i/$max_var"|bc)
  # - as far as I know bc needs "scale" when divide (* bad english?)
  #   otherwise it's truncated to integer.
  # - nicer to use "command <<< text" than "echo text | command"
  parsed_var=$( bc <<< "scale = 3; $i / $max_var" )

  # You must have "$" here
  #f parsed_var max_var &
  f "$parsed_var" "$max_var" &

  # This is wrong here since you are not using the parameters
  # of the script anymore.
  #shift
done

wait

デバッグ行を残します。デバッグで実行すると、次のようになりました。

-$ ./sleeping 1 2 3
declare -a to_sort='([0]="1" [1]="2" [2]="3")'
max_var:3
final_var:.999; $1:.333; $2:3
final_var:1.998; $1:.666; $2:3
final_var:3.000; $1:1.000; $2:3

編集 2: 最後のセクションで使用した名前をデバッグ出力で変更しました。私はこれに出くわしました:
http://www.talisman.org/~erlkonig/documents/commandname-extensions-considered-harmful
ここSOで投稿を読んでいるときに(今は見つけられません)。.shだから私は誰かにスクリプトファイルを使わせて罪を犯したくありません:)

于 2013-02-19T01:05:29.730 に答える