Разбиение на пробелы происходит в вашей команде read
, но вам это все равно не нужно. Кроме того, ваша if
логика ошибочна. Это будет работать, только если my_dir
равно .
, иначе find
не будет генерировать .
на выходе. Наконец, вы указываете в своем примере, что вам нужны только имена каталогов, а не весь путь, но так, как вы его написали, find
передаст путь к стандартному выводу.
Вот более простое решение:
find "$my_dir" -maxdepth 1 -type d -exec basename {} \;|tail -n +2
Хитрость здесь заключается в команде tail
. Вы хотите исключить начальный каталог($my_dir
)из вывода.find
всегда сначала выводит этот каталог (, если вы явно не требуете глубины -первого обхода ), поэтому вам просто нужно удалить первую строку из результирующего вывода.
$ paste data*.txt |
awk -v numOutFlds=4 '{
numFiles = NF / numOutFlds
for (outFldNr=1; outFldNr<=numOutFlds; outFldNr++) {
sum = 0
for (fileNr=1; fileNr<=numFiles; fileNr++) {
inFldNr = outFldNr + ((fileNr - 1) * numOutFlds)
sum += $inFldNr
}
printf "%g%s", sum/numFiles, (outFldNr<numOutFlds ? OFS : ORS)
}
}' |
column -t
0.75 1.25 3 3.25
4 0.75 0.75 3
2.25 1 1.5 1.75
2 1.5 2 1
Предполагая, что я правильно интерпретировал это, вы также можете сделать что-то вроде:
awk
(POSIX):
awk -v n_col=4 '
NF != n_col { next }
FILENAME != file {
file = FILENAME
k = 0
}
{
for (i = 1; i <= n_col; ++i)
A[k++] += $i
}
END {
n_files = ARGC - 1
for (i = 0; i < k; ) {
printf "%2.3f%s", A[i] / n_files,
++i % n_col == 0 ? "\n" : " "
}
}
' data*.txt
perl
:
Я уверен, что это можно сделать лучше, но попробуй.
./script.pl <COLUMNS> data*.txt
#!/usr/bin/env perl
use strict;
use warnings;
my @data;
my $cols = $ARGV[0];
my $ac = $#ARGV;
shift;
for (@ARGV) {
my $k = 0;
open my $fh, '<', $_
or die "Cannot open '$_' - $!";
local $/;
my $fdata = <$fh>;
close $fh;
for ($fdata) {
$data[$k++] += $_ for split;
}
}
my $i = 0;
for (@data) {
printf "%.3f%s", $_ / $ac, ++$i % $cols ? "\t" : "\n";
}
bash:
(Медленно)
Поскольку вы также отметили вопрос bash
, я добавляю, для развлечения, образец того же самого. Довольно медленный по сравнению с perl, awk,...
Обратите внимание, что хотя это и выполнимо, это не лучший инструмент для работы.
Использует башизм для mapfile
, read -a
и т. д.
./script <COLUMNS> data*.txt
#!/bin/bash
declare -i res=1000
declare -i dec=$(( ${#res} - 1 ))
declare -i n_files
declare -i n_columns
declare -a A
process()
{
local m a
mapfile -t m< "$1"
read -ra a<<< "${m[@]}"
for (( i = 0; i < ${#a[*]}; ++i )); do
(( A[i] += a[i] ))
done
(( ++n_files ))
}
n_columns=$1
shift
for f in "$@"; do
process "$f"
done
for (( i = 0; i < ${#A[@]}; ++i )); do
(( (i + 1) % n_columns == 0 )) && sep=$'\n' || sep=' '
printf "%3.${dec}f%s" "$(( res * A[i] / n_files ))e-$dec" "$sep"
done
альтернативный метод печати "плавающий":
(( d = A[i] * res / n_files ))
printf "%3d.%0${dec}d%s" "$(( d / res ))" "$(( d % res ))" "$sep"
Далее sed
... нет , поверьте, я только связываю это:Дополнение с 'sed' ;)
Можно обойтись настольным калькулятором РПНdc
paste./*.txt |
dc -e "2k #2 decimal digits output
[q]sq
[0dddsasbscsd]si # initialize the four registers
[la+sa lb+sb lc+sc ld+sd z3<u]su # update the four registers
[ld4/n9an lc4/n9an
lb4/n9an la4/n10an lix]sp # print results
[?z0=q lux lpx z0=?]s?
lix l?x
"
.75 1.25 3.00 3.25
4.00 .75.75 3.00
2.25 1.00 1.50 1.75
2.00 1.50 2.00 1.00
Perl можно использовать следующим образом:
paste *.txt |
perl -lane '
my @avgs;
while (@F >= 4) {
my @tmp = splice(@F, 0, 4);
$avgs[$#tmp] += pop(@tmp) while @tmp;
}
print join "\t", map { sprintf "%.2f", $_/4.0 } @avgs;
' -
Мы можем использовать GNU sed в сотрудничестве с bc для получения вывода.
n='(\S+)'
paste./*.txt |
sed -Ee "
s/\s+/ /g;s/^ | \$//g
s/\$/ /;s/ /\n/4;ta
:a
s/^$n $n $n $n\n$n $n $n $n (.*)/printf '%d %d %d %d\n%s' \$((\1 + \5)) \$((\2 + \6)) \$((\3 + \7)) \$((\4 + \8)) '\9'/e
s/\n/&/
ta
s/.*/printf '%d\/4\n' &|bc -l|paste -s/e
s/(\...)\S*/\1/g
s/(^|\t)\./\10./g
" -