Як я можу поєднати значення з двох стовпців?


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

1
Не можу повірити, що я отримав відповідь так швидко: О, я ніколи не отримую такої швидкої відповіді на будь-якому іншому форумі :) дякую, що команда спрацювала чудово :)
Syed Jahanzaib

@SyedJahanzaib. Якщо ця відповідь вирішила вашу проблему, будь-ласка, знайдіть хвилинку та прийміть її , натиснувши на галочку зліва. Це означатиме відповідь на питання і спосіб висловлення подяки на сайтах Stack Exchange.
тердон

вибачте, що забув позначити відповідь. і дякую всім також за цінний час та відповіді, вони теж допомогли мені в навчанні досягнення цілей іншим методом :)
Syed Jahanzaib

@SyedJahanzaib, хоча я заробив хороший знак за цю відповідь, я вважаю, що більш точним та всебічним є відповідь Тердона.
taliezin

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. Shell (набагато повільніше / менш ефективно, ніж вище)

    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 тепер, коли мені навіть не приходило в голову. Набагато акуратніше, дякую!
terdon

Я написав це для вас. Зауважте, як не тільки 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 API застосовується в цьому випадку за допомогою команди /адреси (яка завжди є першим компонентом будь- якої команди 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()повинен скласти регулярний вираз, що міститься в рядку, на який вказує аргумент шаблону, і розмістити результати в структурі preg ...

Щоб діяти на цьому, зазначена програма потім посилалася б на regcomp()функцію супутника ...

... [т] regexec()Функція порівнює закінчується нулем рядок , зазначену рядок з скомпільованого регулярного виразу просоченого сполучною инициализируется попереднього виклику regcomp()...

... regexec()повинен заповнити елементи масиву [an] із зміщенням підрядків рядка, які відповідають \(дужкам \)під вираженим виразом візерунка ... сам шаблон вважається субекспресією ...

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


І так, коли я це роблю ...

/[^ ]* */

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

А коли я це роблю ...

//

... щоб вказати на те, що слід використовувати останній визначений регулярний вираз, sedможна просто викликати regexec()повторне використання попередньо складеного регулярного виразу, але, можливо, застосувати його на цей раз до зміненого рядкового аргументу або застосувати нові параметри nmatch як я наказую.

Більш конкретно все-таки ...

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

І так, для кожного рядка sedвведення він записує у свій stdout, враховуючи ваші приклади даних:

[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
    • ditto, але на цей раз число 5000 у верхній частині основного стека висувається одним і стає другим елементом у стеці.
  • +
    • Додайте два найкращих числа в стек разом, випустіть обидва викреслені та натисніть суму на верхню частину стека.
    • У результаті виходить стек, що складається лише з числа 6000.
    • Це синтаксична помилка, якщо будь-який із двох перших елементів у стеці є [рядком ].
  • p
    • pпрошийте верхню частину стека, за якою додається додана \nлінія ewline, не висуваючи її зі складу.
  • c
    • cвивчити стек

Я вважаю, що це працює, але я не можу його розібрати. Загалом ви налаштовуєте додаток для постійного струму. Перша закономірність має сенс. Я думаю, що це відповідає даті та пробілам, але я не розумію, що робить це в дужках класів символів ([&]). Було б чудово, якби ви прописали це.
Джо

1
@Joe - краще?
mikeserv

Оце Так! Це має набагато більше сенсу (і показує мені купу речей, про які мені потрібно дізнатися більше.) Зокрема, я ніколи не помічав використання // для повторного використання поточного шаблону. Це та річ, яку ти читаєш і забуваєш, поки не зіткнешся з фактичним прикладом. Дуже дякую. Це змусило мене сміятися, побачивши, яка сила може бути набрана в незначну команду і скільки потрібно для її пояснення.
Джо

@Joe - ну ... можливо, я зайшов трохи за борт ...
mikeserv
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.