我偶然发现了这个漂亮的bash脚本,这是一个小小的borked。
#!/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
我哪里错了?
答案 0 :(得分: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睡眠处理分数,但许多其他操作系统不会。
答案 1 :(得分:1)
这一行
echo "$1"| read -a to_sort
在子shell中设置to_sort
的值,该子shell在管道完成后不再存在。要设置to_sort
的值并稍后能够使用它,您需要read
命令在当前shell中执行。一种可能性:
read -a to_sort <<< "$1"
答案 2 :(得分: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
我离开调试行,当我使用debug运行它时得到了这个:
-$ ./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
作为脚本文件而感到内疚:)