我有一个文本文件,其中每一行包含两个空白分隔字段:x和y。
1 0 10 29 5 2
现在我想看看y = f(x)的图表,其中x和y取自文件。
我更喜欢curses
终端中的图片,但它也可以是任何图形格式的图片。
最简单的方法是什么bash
?
这是一个非常有趣的可能性。我要在这里向您展示的东西可能不是您想要的,它可能没有优化,可能是一堆垃圾,但它真的很有趣。(我不期待任何赞成票)。
该脚本或多或少地*
在每个点绘制 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
**
**********
***********
* *************** * *
*********************************** ****
**************************************** *
**********************************************
**************************************************
************** **************************************************
******************** ****************************************************
** **************************************************************************
****************************************************************************
** **************************************************************************
******************** ****************************************************
************** **************************************************
**************************************************
**********************************************
**************************************** *
*********************************** ****
* *************** * *
***********
**********
**
gniourf@somewhere:~/cool_path$
*********
**** ***
*** **
** **
** **
** **
*** **
** **
** **
** **
** **
* ** *
** **
** **
** **
** **
** **
*** **
** **
*** ***
*** ***
*** ****
********
gniourf@somewhere:~/an_even_cooler_path$
在您的 OP 中,您提到了“最简单的做法”......好吧,您可以注意到,这个解决方案并不完全是单行的。
xmin!=xmax
以免ymin!=ymax
除以 0xmin
, xmax
, ymin
, 。ymax
bc
tput
了,太慢了,太慢了!相反,构建一个点数组(每个字段包含一个空格或*
)。