2013-09-11 6 views
0

У меня есть текстовый файл со структурой, показанной ниже. Я хотел бы присоединиться к ним в один столбец (суммировать их арифметически и сохранять как один столбец).Как объединить столбцы в Bash

структура файла:

1 4 1 4 
2 5 2 5 
3 6 3 6 

это то, что я хотел бы получить:

10 
14 
18 
+0

суммы столбцов или строк? – devnull

ответ

4

Как об этом:

awk '{ x=0; for(i = 1; i <= NF; i++) x += $i; print x }' file 
+0

Спасибо. У меня есть еще один вопрос; Как отделить эти значения запятыми? – Kristopher

1

В качестве альтернативы (решение AWK лучше, но хорошо известно, что есть альтернативы :))

sed 's/ /+/g' test.txt | sed -E 's/^(.*)$/echo $((\1))/' | bash 
+2

Генерация кода '' '' '' '' '' '' '' '' '' '' 'shh '' более опасна, чем необходимо. – Sorpigal

+0

@Sorpigal: это одна из причин, почему я не рекомендую ее использовать. Это просто для полноты. – Wolph

3

@cnicutar дал стандартное решение AWK, я просто добавить SED Однострочника (РМЖ) для развлечения:

kent$ cat f 
1 4 1 4 
2 5 2 5 
3 6 3 6 

kent$ sed 's/ \+/+/g' f|bc 
10 
14 
18 

\+ в SED линии только в случае, если ваши столбцы разделены несколько -пространствами.

как предложено @ruakh, sed 's/[[:space:]]\+/+/g' f|bc является более общим и надежным.

+1

Эта версия решения 'sed' является лучшим до сих пор. Он включает только один вызов, не разбивается на последовательные пробелы и не использует нестандартный синтаксис. Единственное улучшение, о котором я могу думать, - это сначала обрезать ведущее и конечное пространство. – Sorpigal

+0

@ruakh Вы правы, когда я отправил ответ, вопрос был показан как пробел ... :(, расстояние между «столбцами» было всего лишь одной шириной символа. Ну, '[[: space:]]' в любом случае надежно ,Я изменю ответ – Kent

2

Использование СЭД заменить пробельные плюсах, то bc, чтобы получить результаты:

sed 's/\s\+/+/g' input | bc 
+1

Обратите внимание, что '\ s' является нестандартным и не обязательно будет доступен для не-GNU' sed'. Использование '[[: space:]]' будет эквивалентным. – Sorpigal

6

Для большинства целей, я думаю, что лучше использовать внешнюю программу, такую ​​как AWK или Perl (см ответ cnicutar в в течение AWK); но если вы предпочитаете, вы можете сделать это в чистом Баш, следующим образом:

while read -a arr ; do 
    i=0 
    for field in ${arr[*]} ; do 
     ((i += field)) 
    done 
    echo $i 
done < input-file.txt > output-file.txt 

или более сжато — но и более hackishly — вы могли бы написать:

while read ; do 
    echo $((${REPLY//$'\t'/+})) 
done < input-file.txt > output-file.txt 

(последняя примерно эквивалентно (также хакерские) sed-основе подходы различных других ответов).

+0

Я не думаю, что 'arr' добавляет что-то непереносимое к первому решению. Вы могли бы просто использовать 'while read -r; do i = 0; для поля в $ REPLY; do ... ', эффективно откладывая слово split от' read' до 'for'. Альтернатива для второго решения (для которого +1): 'echo $ (($ (printf% s + $ REPLY) 0))'; который работает с произвольными пробелами, включая конечные пробелы. – rici

1

И вот то же самое в Perl (хотя я уверен, что это может быть сделано более лаконично):

perl -nle '$s=0; $s+=$_ for split; print $s' 

О, и делать то, что ваш заголовок спрашивает (сумма более столбцов вместо строк) :

perl -nle '$i=0; $s[$i++]+=$_ for split; END { print "@s" }' 

... Перл.

Смежные вопросы