テキスト ファイルがあり、各行には 2 つの空白で区切られたフィールドxとyが含まれています。
1 0 10 29 5 2
ここで、xとyがファイルから取得されたy = f(x)のグラフを見たいと思います。
私は端末の画像を好みcurses
ますが、任意のグラフィック形式の画像にすることもできます。
でそれを行う最も簡単な方法は何bash
ですか?
ここに非常に面白い可能性があります。ここで紹介するものは、おそらくあなたが探しているものではなく、おそらく最適化されておらず、おそらくたくさんのがらくたですが、本当に面白いです. (私はそれに対する賛成票を期待していません)。
*
このスクリプトは、(スクリプトの最初の引数として与えられた) ファイルで与えられた座標の各点で多かれ少なかれプロットします。端末の行数と列数を計算します (コマンド を使用して、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
**
**********
***********
* *************** * *
*********************************** ****
**************************************** *
**********************************************
**************************************************
************** **************************************************
******************** ****************************************************
** **************************************************************************
****************************************************************************
** **************************************************************************
******************** ****************************************************
************** **************************************************
**************************************************
**********************************************
**************************************** *
*********************************** ****
* *************** * *
***********
**********
**
gniourf@somewhere:~/cool_path$
*********
**** ***
*** **
** **
** **
** **
*** **
** **
** **
** **
** **
* ** *
** **
** **
** **
** **
** **
*** **
** **
*** ***
*** ***
*** ****
********
gniourf@somewhere:~/an_even_cooler_path$
OPで「最も簡単な方法」と述べました...まあ、このソリューションは正確にはワンライナーではないことに気付くでしょう。
xmin!=xmax
堅牢性: and をチェックしてymin!=ymax
、0 で除算しないようにしますxmin
速度: 、xmax
、ymin
をymax
同じbc
インスタンスで計算しています。tput
もう使用しないでください。速度が遅く、遅すぎました。代わりに、点の配列を作成します (各フィールドにはスペースまたは が含まれます*
)。