- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在开发一个 Linux 的 Bash shell 脚本,它从一个文本文件中提取数据,只留下数字。这些是我的示例解析数据:
3
4
4
5
6
7
8
8
9
11
我想创建一个像这样的简单文本模式条形图,但对应于这些值:
详细信息:
n
(已解析数字)个字符高列适合我。所以在我的例子中左边的第一个栏应该是 3 个字符高,第二个是 4 个,第三个是 4 个,第四个是 5 个,依此类推。更准确地说,对于这个例子,一些东西(使用 █
字符)像:
█
█
██
███
████
█████
██████
███████
█████████
██████████
██████████
██████████
请注意第一列(左)列高 3 个字符,最后一列(右)列高 11 个字符。
使用 $
字符的相同示例,以使其更具可读性:
$
$
$$
$$$
$$$$
$$$$$
$$$$$$
$$$$$$$
$$$$$$$$$
$$$$$$$$$$
$$$$$$$$$$
$$$$$$$$$$
到目前为止,我所知道的最接近的方法是我在其他脚本中使用的进度条方法:
printf "\033[48;5;21m" # Blue background color
for i in $(seq 1 $n); do printf " "; done # Create bar using blue spaces
这是:用 n
空格填充每行打印一个条。但是这个条是水平的,所以在这种情况下不合适。
我请求一些核心循环示例想法来创建此条形图。
在用户 Boardrider 的建议下,接受基于任何类 unix 工具的解决方案。基于用于 Linux shell 的脚本语言(如 Perl 或 Python)的解决方案也被接受,只要它们曾经在许多设备上实现。
最佳答案
这是第一次天真的尝试...这不是一个非常有效的解决方案,因为数据会被多次解析,但它可能会有所帮助。在某种程度上,这是 @Walter_A 提出的第一个循环想法。 .
#!/bin/sh
#
## building a vertical bar graph of data file
## https://stackoverflow.com/q/30929012
##
## 1. required. Data file with one value per line and nothing else!
## /!\ provide the (relative or absolute) file path, not file content
: ${1:?" Please provide a file name"}
test -e "$1" || { echo "Sorry, can't find $1" 1>&2 ; exit 2 ; }
test -r "$1" || { echo "Sorry, can't access $1" 1>&2 ; exit 2 ; }
test -f "$1" || { echo "Sorry, bad format file $1" 1>&2 ; exit 2 ; }
test $( grep -cv '^[0-9][0-9]*$' "$1" 2>/dev/null ) -ne 0 || { echo "Sorry, bad data in $1" 1>&2 ; exit 3 ; }
# setting characters
## 2. optional. Ploting character (default is Dollar sign)
## /!\ for blank color use "\033[48;5;21m \033[0m" or you'll mess...
c_dot="$2"
: ${c_dot:='$'}
## 3. optional. Separator characher (default is Dash sign)
## /!\ as Space is not tested there will be extra characters...
c_sep="$3"
: ${c_sep:='-'}
# init...
len_w=$(wc -l "$1" | cut -d ' ' -f 1 )
l_sep=''
while test "$len_w" -gt 0
do
l_sep="${l_sep}${c_sep}";
len_w=$(($len_w-1))
done
unset len_w
# part1: chart
echo ".${c_sep}${l_sep}${c_sep}."
len_h=$(sort -n "$1" | tail -n 1)
nbr_d=${#len_h}
while test "$len_h" -gt 0
do
printf '| '
for a_val in $(cat "$1")
do
test "$a_val" -ge "$len_h" && printf "$c_dot" || printf ' '
done
echo ' |'
len_h=$(($len_h-1))
done
unset len_h
# part2: legend
echo "|${c_sep}${l_sep}${c_sep}|"
while test "$nbr_d" -gt 0
do
printf '| '
for a_val in $(cat "$1")
do
printf "%1s" $(echo "$a_val" | cut -c "$nbr_d")
done
echo ' |'
nbr_d=$(($nbr_d-1))
done
unset nbr_d
# end
echo "'${c_sep}${l_sep}${c_sep}'"
unset c_sep
exit 0
编辑 1:这是对脚本的修改。它纠正了分隔符处理(只需尝试使用 ' ' 或 '|' 作为要查看的第三个参数),但它可能看起来不太可读,因为我使用参数编号而不是附加变量。
编辑 2:它还处理负整数...您可以更改地面(第 5 个参数)
#!/bin/sh
#
## building a vertical bar graph of data file
## https://stackoverflow.com/q/30929012
##
## 1. required. Data file with one value per line and nothing else!
## /!\ provide the (relative or absolute) file path, not file content
: ${1:?" Please provide a file name"}
[ -e "$1" ] || { echo "Sorry, can't find $1" 1>&2 ; exit 2 ; }
[ -r "$1" ] || { echo "Sorry, can't access $1" 1>&2 ; exit 2 ; }
[ -f "$1" ] || { echo "Sorry, bad format file $1" 1>&2 ; exit 2 ; }
[ $( grep -cv '^[-0-9][0-9]*$' "$1" 2>/dev/null ) -ne 0 ] || { echo "Sorry, bad data in $1" 1>&2 ; exit 3 ; }
## /!\ following parameters should result to a single character
## /!\ for blank color use "\033[48;5;21m \033[0m" or you'll mess...
## 2. optional. Ploting character (default is Dollar sign)
## 3. optional. Horizontal border characher (default is Dash sign)
## 4. optional. Columns separator characher (default is Pipe sign)
## (!) however, when no arg provided the graph is just framed in a table
## 5. optional. Ground level integer value (default is Zero)
test "${5:-0}" -eq "${5:-0}" 2>/dev/null || { echo "oops, bad parameter $5" 1>&2 ; exit 3 ; }
# init...
_long=$(wc -l < "$1" ) # width : number of data/lines in file
if [ -n "$4" ]
then
_long=$((_long*2-3))
fi
_line=''
while [ "$_long" -gt 0 ]
do
_line="${_line}${3:--}"
_long=$((_long-1))
done
unset _long
_from=$(sort -n "$1" | tail -n 1 ) # max int
_stop=$(sort -n "$1" | head -n 1 ) # min int
这次返工有两种形式。第一个产生与前一个类似的输出。
# begin
echo "${4-.}${3:--}${_line}${3:--}${4-.}"
# upper/positive
if [ $_from -gt ${5:-0} ]
then
while [ $_from -gt ${5:-0} ]
do
printf "${4:-| }"
for _cint in $(cat "$1" )
do
if [ $_cint -ge $_from ]
then
printf "${2:-$}$4"
else
printf " $4"
fi
done
echo " ${4:-|}"
_from=$((_from-1))
done
echo "${4-|}${3:--}${_line}${3:--}${4-|}"
fi
unset _from
# center/legend
_long=$(wc -L < "$1" ) # height : number of chararcters in longuest line...
while [ $_long -ge 0 ]
do
printf "${4:-| }"
for _cint in $(cat "$1" )
do
printf "%1s$4" $(echo "$_cint" | cut -c "$_long" )
done
echo " ${4:-|}"
_long=$((_long-1))
done
unset _long
# lower/negative
if [ $_stop -lt ${5:-0} ]
then
_from=${5:-0}
echo "${4-|}${3:--}${_line}${3:--}${4-|}"
while [ $_from -gt $_stop ]
do
printf "${4:-| }"
for _cint in $(cat "$1" )
do
if [ $_cint -lt $_from ]
then
printf "${2:-$}$4"
else
printf " $4"
fi
done
echo " ${4:-|}"
_from=$((_from-1))
done
fi
unset _stop
# end
echo "${4-'}${3:--}${_line}${3:--}${4-'}"
exit 0
注意:当所有值为正(高于地面)或负(低于地面)时,有两次检查以避免额外循环!好吧,也许我应该总是把“中心/图例”部分放在最后?当同时存在正值和负值时,它看起来有点难看,而当只有负整数时,它看起来很奇怪,标签不读相反并且有令人不快的减号。
还要注意 wc -L
is not POSIX... ...因此可能需要另一个循环。
这是另一个变体,其图例编号大小合适,而不是底部。这样做,我节省了一个额外的循环,但我不太喜欢输出(我更喜欢左边的值而不是右边的值,但这是一种味道,不是吗?)
# begin
printf "${4-.}${3:--}${_line}${3:--}${4-.}"
# upper/positive
if [ $_from -gt ${5:-0} ]
then
echo ""
while [ $_from -gt ${5:-0} ]
do
_ctxt=''
printf "${4:-| }"
for _cint in $(cat "$1" )
do
if [ $_cint -ge $_from ]
then
printf "${2:-$}$4"
else
printf " $4"
fi
if [ $_cint -eq $_from ]
then
_ctxt="_ $_from"
fi
done
echo " ${4:-}${_ctxt}"
_from=$((_from-1))
done
_from=$((_from+1))
else
echo "_ ${1}"
fi
# center/ground
if [ $_stop -lt ${5:-0} ] && [ $_from -gt ${5:-0} ]
then
echo "${4-|}${3:--}${_line}${3:--}${4-|}_ ${1}"
fi
# lower/negative
if [ $_stop -lt ${5:-0} ]
then
_from=${5:-0}
while [ $_from -gt $_stop ]
do
_ctxt=''
printf "${4:-| }"
for _cint in $(cat "$1" )
do
if [ $_cint -lt $_from ]
then
printf "${2:-$}$4"
else
printf " $4"
fi
if [ $_cint -eq $((_from-1)) ]
then
_ctxt="_ $_cint"
fi
done
echo " ${4:-|}${_ctxt}"
_from=$((_from-1))
done
fi
# end
unset _from
printf "${4-'}${3:--}${_line}${3:--}${4-'}"
if [ $_stop -lt ${5:-0} ]
then
echo ""
else
echo "_ ${1}"
fi
unset _stop
exit 0
编辑 3:有一些额外的检查,因此当只有正数或负数时不会添加额外的底线。
最后,我认为最终的解决方案是两者的混合,其中值显示在侧面,值的位置显示在中心。然后它更接近 GNU Plot 的输出。
# init...
_long=$(wc -l < "$1" )
if [ -n "$4" ]
then
_long=$((_long*2-3))
fi
_line=''
while [ $_long -gt 0 ]
do
_line="${_line}${3:--}"
_long=$((_long-1))
done
unset _long
_from=$(sort -n "$1" | tail -n 1 ) # max int
_stop=$(sort -n "$1" | head -n 1 ) # min int
# begin
echo "${4-.}${3:--}${_line}${3:--}${4-.}"
# upper/positive
if [ $_from -gt ${5:-0} ]
then
while [ $_from -gt ${5:-0} ]
do
_ctxt=''
printf "${4:-| }"
for _cint in $(cat "$1" )
do
if [ $_cint -ge $_from ]
then
printf "${2:-$}$4"
else
printf " $4"
fi
if [ $_cint -eq $_from ]
then
_ctxt="_ $_from"
fi
done
echo " ${4:-|}$_ctxt"
_from=$((_from-1))
done
echo "${4-|}${3:--}${_line}${3:--}${4-|}"
fi
# center/ground
_size=$(wc -l < "$1" ) # width : number of data/lines in file
##_long=${#_size} # height : number of chararcters in long
#_long=1
##while [ $_long -gt 0 ]
#while [ $_long -le ${#_size} ]
#do
#_rank=1
#printf "${4:-| }"
#while [ $_rank -le $_size ]
#do
#printf "%1s$4" $( printf "%0${#_size}d" $_rank | cut -c $_long )
#_rank=$((_rank+1))
#done
#printf " ${4:-|}"
##_long=$((_long-1))
#_long=$((_long+1))
##if [ $_long -eq 0 ]
#if [ $_long -eq ${#_size} ]
#then
#printf "_ ${1}"
#fi
#echo ''
#done
_rank=1
printf "${4:-| }"
while [ $_rank -le $_size ]
do
printf "%1s$4" $( expr "$_rank" : '.*\(.\)$' )
_rank=$((_rank+1))
done
echo " ${4:-|}_ ${1}"
# lower/negative
if [ $_stop -lt ${5:-0} ]
then
echo "${4-|}${3:--}${_line}${3:--}${4-|}"
while [ $_from -gt $_stop ]
do
_ctxt=''
printf "${4:-| }"
for _cint in $(cat "$1" )
do
if [ $_cint -lt $_from ]
then
printf "${2:-$}${4}"
else
printf " $4"
fi
if [ $_cint -eq $((_from-1)) ]
then
_ctxt="_ $_cint"
fi
done
echo " ${4:-|}$_ctxt"
_from=$((_from-1))
done
fi
unset _from
unset _stop
# end
echo "${4-'}${3:--}${_line}${3:--}${4-'}"
exit 0
最后的改进是扩展能力......
关于bash - 外壳 : How can I make a text-mode bar chart from parsed data (numbers)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30929012/
我并不总是编写 make 文件,但当我这样做时,我喜欢尝试并写好它们。试图使界面与其他开发人员的期望一致始终是一项艰巨的任务。我正在寻找的是所有常见的 make some clean (GNU) ma
例如,我在运行 makefile 时收到这样的错误: make[3]: *** [/home/ziga/Downloads/openwrt/rakun_openwrt/staging_dir/ho
我必须创建一个 Makefile,它从不同文件夹中的 .c 文件创建单个可执行文件。 .c 文件包含来自任何这些文件夹的头文件。根目录有3个子目录x/y、x/z、a,所有这些子目录都有一些.c和.h文
您好,我有一个简单的 MakeFile,其中包含: clean: rm -f ex1 但是当我运行命令make clean 时,出现以下错误: make: *** No rule to mak
我已经为一些软件安装了它,但现在我根本不使用那个软件,所以我需要移除MinGW才能使用Cygwin进行Android开发。。我使用的是64位Windows 7
以下是针对我遇到的问题的简化生成文件: all: /tmp/makey/../filey @echo All done /tmp/filey: @echo Filey 当我运行 mak
获取错误: make: *** No rule to make target all. Stop." 在安装nagios主机期间运行此命令make all 最佳答案 可能的常见错误: 确保将文件命名为
当使用 -jN 运行 gnu-make 规则时,make 会创建 jobserver用于管理跨子制造商的工作数量。此外,您可以通过在 make 配方前添加 + 前缀来“将作业服务器环境传递”到 mak
使用 GNU Make 4.1 概括 我调用一个子品牌 b.mk来自生成文件 a.mk .b.mk被调用以确保构建子系统。 有时我想强制一个目标为 a.mk重制: make -f a.mk --al
这个问题与问题 2543127 的精神相似。 . 我有一个带有头文件列表的 gnu makefile。每个头文件可能位于不同的目录中,例如, HEADERS = $(wildcard *.h) $(w
假设我有以下 GNU make 目标: create_dir: @mkdir objects build_asm: $(ASM_FILES) @echo
我有一个具有以下结构的 Makefile(工作示例)。 .PHONY: image flashcard put-files put-files: @echo "=== put-files" i
我想要一个这样的makefile: cudaLib : # Create shared library with nvcc ocelotLib : # Create shared li
有没有比更好的方法来获取 GNU make 变量的第一个字符 FIRST=$(shell echo $(VARIABLE) | head -c 1) (不仅笨重而且还要调用外部shell)? 最佳答案
我通常使用像 cmake 这样的高级构建系统来构建我的 C/C++ 代码。但是由于各种原因,我直接使用 GNU make。 我正在进行递归构建,其中每个目录都有一个 makefile。 我最近不得不将
我通常使用像 cmake 这样的高级构建系统来构建我的 C/C++ 代码。但是由于各种原因,我直接使用 GNU make。 我正在进行递归构建,其中每个目录都有一个 makefile。 我最近不得不将
我安装了最新的mingw,发现没有mingw32-make了。有make.exe,所以我想知道最近是否将mingw32-make重命名为make.exe。 最佳答案 我不知道您从哪里获得 MinGW,
我正在使用 CentOS,但由于一个错误,许多软件包被删除了。所以我没有 yum 和 rpm。所以我想从源代码手动制作 yum,但我也没有制作。我知道一切都会用“制作包”制作。但是 make 自己呢?
考虑这个Makefile: .PHONY: all all: main.txt main.txt: build/main.txt cp build/main.txt . %/main.txt:
假设目录输入中有 1000 个扩展名为 .xhtml 的文件,并且这些文件的某个子集(输出路径在 $(FILES) 中)需要通过 xslt 转换为目录输出中具有相同名称的文件.一个简单的 make 规
我是一名优秀的程序员,十分优秀!