阅读专栏并查找中位数 (Bash)
Reading Column and Find Median (Bash)
我想找到每列的中位数,但它并不像我想要的那样工作。
1 2 3
3 2 1
2 1 5
我期待
2 2 3
结果,但事实证明它只给出了总和误差和一些 "sum" 的列。下面是 "median in column"
的代码片段
while read -r line; do
read -a array <<< "$line"
for i in "${!array[@]}"
do
column[${i}]=${array[$i]}
((length[${i}]++))
result=${column[*]} | sort -n
done < file
for i in ${!column[@]}
do
#some median calculation.....
注意:我想练习 bash,这就是我使用 bash 硬编码的原因。
如果有人能帮助我,我真的很感激,尤其是在 BASH 中。谢谢。
Bash 确实不适合这样的低级文本处理:read
命令对其读取的每个字符 进行系统调用 ,这意味着它很慢,而且是 CPU 猪。处理交互式输入还可以,但将其用于一般文本处理就很疯狂了。为此使用 awk(Python、Perl 等)会好得多。
作为学习Bash的练习,我猜测没问题,但请尽量避免在实际程序中使用read
进行批量文本处理。有关详细信息,请参阅 Unix 和 Linux Stack Exchange 站点上的 Why is using a shell loop to process text considered bad practice?,尤其是
Stéphane Chazelas(Shellshock Bash 错误的发现者)。
无论如何,回到你的问题... :)
你的大部分代码都可以,但是
result=${column[*]} | sort -n
没有按照您的意愿去做。
这是获得纯 Bash 列中位数的一种方法:
#!/usr/bin/env bash
# Find medians of columns of numeric data
# See
# Written by PM 2Ring 2015.10.13
fname=
echo "input data:"
cat "$fname"
echo
#Read rows, saving into columns
numrows=1
while read -r -a array; do
((numrows++))
for i in "${!array[@]}"; do
#Separate column items with a newline
column[i]+="${array[i]}"$'\n'
done
done < "$fname"
#Calculate line number of middle value; which must be 1-based to use as `head`
#argument, and must compensate for extra newline added by 'here' string, `<<<`
midrow=$((1+numrows/2))
echo "midrow: $midrow"
#Get median of each column
result=''
for i in "${!column[@]}"; do
median=$(sort -n <<<"${column[i]}" | head -n "$midrow" | tail -n 1)
result+="$median "
done
echo "result: $result"
输出
input data:
1 2 3
3 2 1
2 1 5
midrow: 3
result: 2 2 3
我想找到每列的中位数,但它并不像我想要的那样工作。
1 2 3
3 2 1
2 1 5
我期待
2 2 3
结果,但事实证明它只给出了总和误差和一些 "sum" 的列。下面是 "median in column"
的代码片段while read -r line; do
read -a array <<< "$line"
for i in "${!array[@]}"
do
column[${i}]=${array[$i]}
((length[${i}]++))
result=${column[*]} | sort -n
done < file
for i in ${!column[@]}
do
#some median calculation.....
注意:我想练习 bash,这就是我使用 bash 硬编码的原因。 如果有人能帮助我,我真的很感激,尤其是在 BASH 中。谢谢。
Bash 确实不适合这样的低级文本处理:read
命令对其读取的每个字符 进行系统调用 ,这意味着它很慢,而且是 CPU 猪。处理交互式输入还可以,但将其用于一般文本处理就很疯狂了。为此使用 awk(Python、Perl 等)会好得多。
作为学习Bash的练习,我猜测没问题,但请尽量避免在实际程序中使用read
进行批量文本处理。有关详细信息,请参阅 Unix 和 Linux Stack Exchange 站点上的 Why is using a shell loop to process text considered bad practice?,尤其是
Stéphane Chazelas(Shellshock Bash 错误的发现者)。
无论如何,回到你的问题... :)
你的大部分代码都可以,但是
result=${column[*]} | sort -n
没有按照您的意愿去做。
这是获得纯 Bash 列中位数的一种方法:
#!/usr/bin/env bash
# Find medians of columns of numeric data
# See
# Written by PM 2Ring 2015.10.13
fname=
echo "input data:"
cat "$fname"
echo
#Read rows, saving into columns
numrows=1
while read -r -a array; do
((numrows++))
for i in "${!array[@]}"; do
#Separate column items with a newline
column[i]+="${array[i]}"$'\n'
done
done < "$fname"
#Calculate line number of middle value; which must be 1-based to use as `head`
#argument, and must compensate for extra newline added by 'here' string, `<<<`
midrow=$((1+numrows/2))
echo "midrow: $midrow"
#Get median of each column
result=''
for i in "${!column[@]}"; do
median=$(sort -n <<<"${column[i]}" | head -n "$midrow" | tail -n 1)
result+="$median "
done
echo "result: $result"
输出
input data:
1 2 3
3 2 1
2 1 5
midrow: 3
result: 2 2 3