2

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

1 0
10 29
5 2

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

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

最简单的方法是什么bash

4

1 回答 1

5

这是一个非常有趣的可能性。我要在这里向您展示的东西可能不是您想要的,它可能没有优化,可能是一堆垃圾,但它真的很有趣。(我不期待任何赞成票)。

该脚本或多或少地*在每个点绘制 a,其坐标在文件中给出(作为脚本的第一个参数给出)。它计算终端的行数和列数(使用命令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 > Mset或者./genMandelbrot 100 50 > 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!=xmax以免ymin!=ymax除以 0
  • 速度:在同一实例中计算xmin, xmax, ymin, 。ymaxbc
  • 速度:不要再用tput了,太慢了,太慢了!相反,构建一个点数组(每个字段包含一个空格或*)。

待办事项。

  • 有很多东西可以让我们真正舒适地使用。这个练习留给读者。
于 2012-12-08T18:09:37.957 回答