【问题标题】:How to draw a graph from text file in bash?如何从 bash 中的文本文件中绘制图形?
【发布时间】:2012-12-08 12:31:49
【问题描述】:

我有一个文本文件,每行包含两个空格分隔的字段:xy

1 0 10 29 5 2

现在我想看看 y = f(x) 的图形,其中 xy 取自文件。

我更喜欢终端中的curses 图片,但它也可以是任何图形格式的图片。

bash 中最简单的方法是什么?

【问题讨论】:

    标签: bash graph curses


    【解决方案1】:

    这是一个非常有趣的可能性。我要在这里向您展示的东西可能不是您想要的,它可能没有优化,可能是一堆垃圾,但它真的很有趣。 (我不希望有人支持它)。

    此脚本或多或少在每个点绘制*,其坐标在文件中给出(作为脚本的第一个参数给出)。它计算终端的行数和列数(使用命令stty,如果你碰巧安装了它,那很好,否则,好吧,它不会工作)。

    #!/bin/bash
    
    isnumber() {
       for i; do
          [[ "$i" =~ [[:digit:]] ]] || return 1
          [[ "$i" =~ ^[+-]?[[:digit:]]*\.?[[:digit:]]*$ ]] || return 1
       done
       return 0
    }
    
    die() {
       echo >&2 "$@"
       exit 1
    }
    
    [[ -n $1 ]] || die "You must provide an argument"
    
    xarray=()
    yarray=()
    
    # Read file input
    while read x y _; do
       isnumber "$x" "$y" || continue
       xarray+=( "$x" )
       yarray+=( "$y" )
    done < "$1"
    
    # Check that we have at least one point
    (( ${#xarray[@]} )) || die "Error, there's no valid point inf file \`$1'"
    
    # Compute xmin, xmax, ymin and ymax:
    read xmin xmax ymin ymax valid < <(
       bc -l < <(
          echo "ymin=${yarray[0]}; ymax=${yarray[0]}"
          echo "xmin=${xarray[0]}; xmax=${xarray[0]}"
          for i in "${!xarray[@]}"; do
             echo "y=${yarray[i]}; if (ymax<y) ymax=y; if (ymin>y) ymin=y"
             echo "x=${xarray[i]}; if (xmax<x) xmax=x; if (xmin>x) xmin=x"
          done
          echo 'print xmin," ",xmax," ",ymin," ",ymax'
          # This will tell us if we have xmin<xmax and ymin<ymax
          echo 'print " ",(xmin<xmax)*(ymin<ymax)'
       )
    )
    
    # Check that xmin<xmax and ymin<ymax
    (( valid )) || die "Error, ! ( (xmin<xmax) && (ymin<ymax) )"
    
    # Get terminal's number of rows and columns
    IFS=' ;' read _ _ _ _ nbrows _ nbcols _ < <(stty -a)
    ((nbrows-=1))
    ((maxcols=nbcols-1))
    ((maxrows=nbrows-1))
    
    # Create an array full of spaces:
    points=()
    for ((i=0;i<nbrows*nbcols;++i)); do points+=( ' ' ); done
    
    # Put a '*' at each x y in array points
    while read r c; do
       printf -v X "%.f" "$c"
       printf -v Y "%.f" "$r"
       points[X+Y*nbcols]='*'
    done < <(
       bc -l < <(
          echo "xmin=$xmin; dx=$maxcols/($xmax-xmin)"
          echo "ymax=$ymax; dy=$maxrows/(ymax-($ymin))"
          for i in "${!xarray[@]}"; do
             echo "print (ymax-(${yarray[i]}))*dy,\" \",(${xarray[i]}-xmin)*dx,\"\n\""
          done
       )
    )
    
    # Now, print it! The clear is not mandatory    
    clear
    printf "%c" "${points[@]}"
    

    调用脚本plot_file_in_terminal(或者更短的名称)。

    您可以尝试一下,非常有趣,使用 Mandelbrot 集:以下脚本生成 M 集(您可以将 x 和 y 坐标的像素数作为输入,好吧,通过以下方式计算出一些东西你自己):

    #!/bin/bash
    
    die() {
       echo >&2 "$@"
       exit 1
    }
    
    nbx=${1:-100}
    nby=${2:-100}
    Nmax=${3:-100}
    
    [[ $nbx =~ ^[[:digit:]]+$ ]] && ((nbx>5)) || die "First argument (nbx) must be an integer > 5"
    [[ $nby =~ ^[[:digit:]]+$ ]] && ((nby>5)) || die "Second argument (nby) must be an integer > 5"
    [[ $Nmax =~ ^[[:digit:]]+$ ]] && ((Nmax>5)) || die "Third argument (Nmax) must be an integer > 5"
    
    xmin=-1.5
    xmax=1
    ymin=-1
    ymax=1
    
    bc -l <<EOF
    for (k=0;k<$nbx;++k) {
       for (l=0;l<$nby;++l) {
          x0=k*($xmax-($xmin))/($nbx-1)+($xmin)
          y0=l*($ymax-($ymin))/($nby-1)+($ymin)
          x=x0
          y=y0
          isin=1
          for (i=0;i<$Nmax;++i) {
             if(x^2+y^2>1) {
                isin=0
                break
             }
             xn=x^2-y^2+x0
             y=2*x*y+y0
             x=xn
          }
          if(isin) print x0," ",y0,"\n"
       }
    }
    EOF
    

    将其命名为 genMandelbrot 并将其用作 ./genMandelbrot &gt; Mset./genMandelbrot 100 50 &gt; Mset(如果您的终端大小约为 100x50)。那么:

    ./plot_file_in_terminal Mset
    

    不错,嗯?

    如果你想要一个正弦函数(比如从 0 到 2*pi):

    bc -l <<< "for (i=0;i<400;++i) { x=i*6.28/400; print x,\" \",s(x),\"\\n\" }" > sine
    

    然后调用:

    ./plot_file_in_terminal sine
    

    输出

    曼德布罗套装(80x24)

                                                            **
                                                        **********
                                                      ***********
                                                 *  *************** *   *
                                        *********************************** ****
                                        **************************************** *
                                    **********************************************
                                  **************************************************
             **************       **************************************************
           ******************** ****************************************************
     **  **************************************************************************
    ****************************************************************************
     **  **************************************************************************
           ******************** ****************************************************
             **************       **************************************************
                                  **************************************************
                                    **********************************************
                                        **************************************** *
                                        *********************************** ****
                                                 *  *************** *   *
                                                      ***********
                                                        **********
                                                            **
    gniourf@somewhere:~/cool_path$ 
    

    正弦波(80x24)

                    *********
                 ****       ***
               ***             **
              **                 **
            **                    **
           **                       **
         ***                         **
        **                            **
       **                               **
      **                                 **
     **                                   **
    *                                      **                                      *
                                            **                                    **
                                             **                                 **
                                               **                              **
                                                **                            **
                                                 **                          **
                                                  ***                      **
                                                    **                    **
                                                     ***                ***
                                                       ***            ***
                                                         ***       ****
                                                            ********    
    gniourf@somewhere:~/an_even_cooler_path$ 
    

    在您的 OP 中,您提到了“最简单的做法”......好吧,您可以注意到,这个解决方案并不完全是单行的。

    编辑。

    • 鲁棒性:检查xmin!=xmaxymin!=ymax不被0除
    • 速度:在同一 bc 实例中计算 xminxmaxyminymax
    • 速度:不要再使用tput,它太慢了,太慢了!相反,构建一个点数组(每个字段包含一个空格或*)。

    待办事项。

    • 有很多东西可以让我们真正舒适地工作。这个练习留给读者。

    【讨论】:

    • +1 对可用资源的出色利用,我可以想象在 1985 年花了整整几分钟时间在我的 VT100 上探索 Mandelbrot 人物的复杂性!
    • @msw 这让我们感觉自己是先驱,就像 Mandelbrot 一样,他在 1980 年 3 月 1 日得到了this picture(这是我唯一可以使用 google 快速找到的)。如果您碰巧有 The Beauty of Fractals 一书,您会发现 B. Mandelbrot 的一篇不错的文章,其中附有他的第一张照片的副本(图 57,第 152 页)。
    • 该图需要为每个点添加第三个参数来改变打印的字符。我真的不会浪费时间去做这件事。真的。
    猜你喜欢
    • 2020-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多