2

テキスト ファイルがあり、各行には 2 つの空白で区切られたフィールドxyが含まれています。

1 0
10 29
5 2

ここで、xyがファイルから取得されたy = f(x)のグラフを見たいと思います。

私は端末の画像を好みcursesますが、任意のグラフィック形式の画像にすることもできます。

でそれを行う最も簡単な方法は何bashですか?

4

1 に答える 1

5

ここに非常に面白い可能性があります。ここで紹介するものは、おそらくあなたが探しているものではなく、おそらく最適化されておらず、おそらくたくさんのがらくたですが、本当に面白いです. (私はそれに対する賛成票を期待していません)。

*このスクリプトは、(スクリプトの最初の引数として与えられた) ファイルで与えられた座標の各点で多かれ少なかれプロットします。端末の行数と列数を計算します (コマンド を使用して、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(または短い名前) を呼び出します。

試してみてください。非常に面白いです。マンデルブロー集合を使用します。次のスクリプトは M-set を生成します (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

それに名前を付けて、または端末が多かれ少なかれ100x50の場合genMandelbrotに使用します。それで:./genMandelbrot > Mset./genMandelbrot 100 50 > Mset

./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堅牢性: and をチェックしてymin!=ymax、0 で除算しないようにします
  • xmin速度: 、xmaxyminymax同じbcインスタンスで計算しています。
  • 速度:tputもう使用しないでください。速度が遅く、遅すぎました。代わりに、点の配列を作成します (各フィールドにはスペースまたは が含まれます*)。

トドス。

  • 実際に快適に作業できるものがたくさんあります。この演習は読者に任せます。
于 2012-12-08T18:09:37.957 に答える