【问题标题】:bash: Iterating over a range of floating-point valuesbash:迭代一系列浮点值
【发布时间】:2016-07-11 16:42:26
【问题描述】:

我有以下问题:
我想从 shell 运行以下命令:

python test.py -f fname.csv -s 0.0 -c 0.0 > outS0.0C0.0.txt

问题是我希望 s 和 c 循环遍历从 0.0 到 1.0 的所有值,并将结果存储到上述格式的文件中。此外,如果可能,将输出文件分别移动到子文件夹,例如:在 .\S0.0 中,所有以 outS0.0* 开头的 s 的 out* 文件等等。所以结果将是相应文件的子文件夹集。

谢谢!

【问题讨论】:

  • 如果您循环遍历从 0.0 到 1.0 的所有值,则为解释是 0.0、0.1、0.2 等还是可能是 0.0、0.01、0.02 等留下了一些解释空间。除此之外,到目前为止,您尝试过什么?你试过在 Bash 中使用for-statement 吗?通常希望您在发布到 SO 时在实际代码方面付出一些努力。
  • 你试过什么?在数学上,一个范围内的“所有值”是一个无限集,尽管标准浮点数学的有限精度将其限制为 2^46 个离散数字。
  • 而且你也不能用谷歌...?
  • ABS 是一个非常糟糕的参考选择。考虑一下 Wooledge BashGuide——mywiki.wooledge.org/BashGuide——或 bash-hackers wiki。
  • 关于浮点数学,在 BashFAQ #22 中有介绍:mywiki.wooledge.org/BashFAQ/022

标签: bash macos shell


【解决方案1】:

这样就可以了,不需要任何工具(例如seq),POSIX 或 bash 的文档都没有指定:

#!/bin/bash
#      ^^^^- not /bin/sh; bash is required for C-style for loop syntax

for ((s=0; s<=10; s++)); do
  for ((c=0; c<=10; c++)); do
    s_str=$(awk -v i="$s" 'BEGIN { printf "%1.1f\n", i / 10 }')
    c_str=$(awk -v i="$c" 'BEGIN { printf "%1.1f\n", i / 10 }')
    python test.py -f fname.csv -s "$s_str" -c "$c_str" >"outS${s_str}C${c_str}.txt"
  done
done

【讨论】:

    【解决方案2】:

    Bash 无法进行浮点数学运算。但是您可以使用 awk 来创建数字。

    #!/bin/sh
    
    counter() {
        awk 'BEGIN { for (i=0.0; i<=1; i+=0.1) { printf("%.1f\n",i) } }'
    }
    
    counter | while read s; do
        mkdir -p S${s}
        counter | while read c; do
            python test.py -f fname.csv -s ${s} -c ${c} > outS${s}C${c}.txt
            mv outS${s}C${c}.txt S${s}/
        done
    done
    

    这将为s 的每个值创建目录,然后为sc 的每个值运行您的python 命令,将每个结果文件移动到目标目录中。我假设您有理由不将输出重定向到该目标目录中已经存在的文件中 - 否则,删除 mv 并执行以下操作会更有意义:

            python test.py -f fname.csv -s ${s} -c ${c} > S${s}/outS${s}C${c}.txt
    

    如果您希望计数器使用其他数字,可以很容易地向这个 shell 函数添加选项,使其表现得像 seqjot

    【讨论】:

      【解决方案3】:
      #!/bin/sh
      for ((s=0; s<=10; s++)); do
        for ((c=0; c<=10; c++)); do
          s_str=$(awk -v i="$s" 'BEGIN { printf "%1.1f\n", i / 10 }')
          c_str=$(awk -v i="$c" 'BEGIN { printf "%1.1f\n", i / 10 }')
          s_str=$(sed 's/,/./' <<< $s_str)
          c_str=$(sed 's/,/./' <<< $c_str)
          mkdir -p S${s_str}
          echo "Doing case:  S=${s_str},  C=${c_str}"
          python test.py -f fname.csv -s "$s_str" -c "$c_str"  > "outS${s_str}C${c_str}.txt"
          mv outS${s_str}C${c_str}.txt S${s_str}/
        done
      done                                                                                                                                                   
      

      【讨论】:

        猜你喜欢
        • 2012-08-07
        • 1970-01-01
        • 2021-01-11
        • 1970-01-01
        • 2020-10-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多