Как я могу объединить значения из двух столбцов?

11

У меня есть файл в следующем формате:

$ cat /tmp/raw
2015-01   5000   1000
2015-02   6000   2000
2015-03   7000   3000

Теперь я хочу получить объединенное значение из столбцов 2 и 3 в каждой строке, чтобы получить следующие результаты:

2015-01   6000
2015-02   8000
2015-03   9000

Я пробовал это, но он показывает только последнее значение в файле, как значение 2015-03.

Сайед Джаханзаиб
источник

Ответы:

11

Вы можете попробовать использовать awk:

awk '{ print $1, $2 + $3; }' /tmp/raw

Результат будет (я полагаю, значение для 2015-03 должно быть 10000):

2015-01 6000
2015-02 8000
2015-03 10000
taliezin
источник
1
Я не могу поверить, что я получил ответ так быстро: O, я никогда не получал такой быстрый ответ ни на одном другом форуме :) спасибо, что команда работала отлично :)
Сайед Джаханзаиб
@SyedJahanzaib, если этот ответ решил вашу проблему, пожалуйста, найдите время и примите его , нажав на флажок слева. Это пометит вопрос как ответивший и выразит благодарность на сайтах Stack Exchange.
Terdon
извините, я забыл отметить ответ. и спасибо всем остальным за то, что там было драгоценное время и ответы, они также помогли мне в обучении достижению целей другим методом :)
Сайед Джаханзаиб
@SyedJahanzaib, хотя я получил хороший значок за этот ответ, я думаю, что более точным и исчерпывающим является ответ Тердона.
Тализин
16

Вот несколько способов:

  1. Еще один подход awk

    awk '{$2+=$3;}NF--' file
    
  2. Perl

    perl -lane 'print "$F[0] ",$F[1]+$F[2]' file
    

    или

    perl -ape 's/$F[1].*/$F[1]+$F[2]/e' file
    
  3. Оболочка (намного медленнее / менее эффективна, чем указано выше)

    while read a b c; do echo "$a $((b + c))"; done < file
    
Тердон
источник
2
$2+=$3может быть более ненадежным
123
@ User112638726 так и есть. Благодарю.
Тердон
3
Вы также можете использовать, awk '{$2+=$3}NF--'чтобы не осталось пустого поля 3. Хотя это только мое предпочтение, и оно слишком похоже на пост в качестве ответа само по себе :)
123
1
@ User112638726 теперь, когда мне даже не пришло в голову. Намного аккуратнее, спасибо!
Тердон
Я написал это для вас. Обратите внимание, что не только sedкаким-то образом удается понять поля - даже определять поля на лету, а также поля с полями - но, как, очевидно, и происходит, вся концепция сопоставления регулярных выражений Unix фактически основана на разделении строки на поля согласно шаблону ! Кто знал?
mikeserv
5
sed 's/[^ ]* */[&]P/;s//&+pc/3'|dc

... печать ...

2015-01   6000
2015-02   8000
2015-03   10000

Итак, выше я объявляю регулярное выражение, которое определяет экстент поля , состоящий из одной последовательности символов *переменной длины, которые ^не являются <пробелом>, за которыми сразу же следует одна последовательность символов *переменной длины, которые являются <пробелом> . Это объявление применяется к sedпространству паттернов России, которое представляет собой строку, разделенную (по умолчанию) каждым \nсимволом ewline, которая встречается на входе, и которая рекурсивно заменяется (по умолчанию) на следующий для каждого вхождения того же самого.

Интерфейс для этой декларации двоякий, и на каждом уровне он полностью регулируется и определяется по крайней мере одним международным официальным комитетом стандартов IEEE для обеспечения предсказуемого применения sedкомандного синтаксиса. sedСинтаксис API , например, в этом случае применяется с помощью команды /address (которая всегда является первым компонентом любой команды ubstitution) , но его содержимое интерпретируется более базовым API как подмножество, указанное для функция в стандартной библиотеке C ./sed s///regcomp()

Я могу сделать эти заявления уверенно, потому что sedэто не просто программа, а, скорее, скомпилированный исполняемый файл, названный sedна моей Unix-подобной машине, является реализацией четко определенного, исторически сложившегося и управляемого стандартами sed приложения моей системы. библиотеки соответствия выражений.


Из sedспецификации:

sedУтилита должна поддерживать Brès , описанный в XBD основных регулярных выражений ...

... где мы находим ...

Оба Brès и EREs поддерживаются Regular Expression Matching интерфейс в объеме системы Интерфейсы POSIX.1-2008 под regcomp(), regexec()и функции , связанные.

Приложение, которое вызывает regcomp(), представит ему строку шаблона и ...

... [t] regcomp()Функция he должна скомпилировать регулярное выражение, содержащееся в строке, на которую указывает аргумент шаблона, и поместить результаты в структуру preg ...

Чтобы действовать в этом направлении, указанное приложение будет ссылаться на regcomp()сопутствующую функцию ...

... [t] regexec()Функция he сравнивает строку с нулем в конце, указанную в строке, с скомпилированным регулярным выражением preg, инициализированным предыдущим вызовом regcomp()...

... regexec()заполняет элементы [с] массивом с смещениями подстрок строки , которые соответствуют в \(скобках подвыражения \)из шаблона ... узора сам по себе считается подвыражениями ...

... [t] regexec()функция должна заполнять все элементы nmatch в pmatch , где nmatch и pmatch предоставляются приложением, даже если некоторые элементы pmatch не соответствуют подвыражениям в шаблоне .


И так, когда я делаю ...

/[^ ]* */

... sedсначала компилирует регулярное выражение и сохраняет результаты в памяти, а затем применяет скомпилированный автомат, хранящийся там, к содержимому моего пространства шаблонов столько раз, сколько необходимо для выполнения моей команды. Каждый раз, когда это происходит, результатом является массив из одного или более полей с нулевым разделением, которые разграничиваются смещениями, возвращаемыми regexec().

И когда я делаю ...

//

... чтобы указать, что следует использовать последнее определенное регулярное выражение, sedможно просто regexec()снова вызвать повторно скомпилированное регулярное выражение, но, возможно, применить его на этот раз к измененному строковому аргументу или применить новые параметры nmatch в качестве команды I.

Точнее еще ...

  • s/[^ ]* */[&]P/
    • замените первое вхождение pattern в pattern-space на [левую квадратную скобку, затем на &себя, затем на ]правую квадратную скобку, за которой следует Pсимвол.
  • s//&+pc/3
    • примените последнее использованное регулярное выражение снова к текущему пространству шаблона и замените 3третье вхождение шаблона в пространстве шаблона на &себя, за которым следует добавленная строка +pc.

И поэтому для каждой строки sedввода он записывает в свой стандартный вывод, учитывая данные вашего примера:

[2015-01   ]P5000   1000+pc
[2015-02   ]P6000   2000+pc
[2015-03   ]P7000   3000+pc

Это может показаться странным, но dcкалькулятор заключает в кавычки строки в своих входных данных в квадратных скобках, и Pкоманда будет печатать верхнюю часть стека без добавления \newline, а затем выталкивать его из стека ввода.

И так, используя первую строку там в качестве примера, dcсделаем:

  • [2015-01 ]P
    • Pнабросать и вытолкнуть вершину стека
  • 5000
    • Вставьте число 5000в верхнюю часть стека и сдвиньте все элементы, находящиеся в данный момент в стеке (теперь их нет) , на единицу.
  • 1000
    • То же самое, но на этот раз число 5000 в верхней части основного стека уменьшается на единицу и становится вторым элементом в стеке.
  • +
    • Сложите два верхних числа в стеке, вытяните оба из стека и поместите сумму в верхнюю часть стека.
    • В результате получается стек, состоящий только из числа 6000.
    • Это синтаксическая ошибка, если любой из двух верхних элементов в стеке является [строкой ].
  • p
    • pОтпечатайте вершину стека, а затем добавленную \newline, не выталкивая ее из стека.
  • c
    • cучить стек
mikeserv
источник
Я верю, что это работает, но я не могу разобрать это. В общем, вы настраиваете дополнение для DC. Первый шаблон имеет смысл. Я думаю, что это совпадает с датой и конечными пробелами, но я не понимаю, что делать, помещая это в скобки класса символов ([&]). Было бы здорово, если бы вы это изложили.
Джо
1
@ Джо - лучше?
mikeserv
Вот это да! Это имеет гораздо больше смысла (и показывает мне кучу вещей, о которых мне нужно узнать больше.) В частности, я никогда не замечал использования // для повторного использования текущего шаблона. Это то, что вы читаете и забываете, пока не наткнетесь на реальный пример. Большое спасибо. Это заставило меня рассмеяться, увидев, сколько энергии можно собрать в крошечную команду и сколько нужно, чтобы объяснить это.
Джо
@ Джо - ну ... может быть, я немного
переборщил