ฉันจะรวมค่าจากสองคอลัมน์เข้าด้วยกันได้อย่างไร


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 ควรเป็น 10,000):

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

1
ฉันไม่สามารถเชื่อว่าฉันได้ตอบนี้อย่างรวดเร็วโอ้ฉันไม่เคยได้รับการตอบกลับอย่างรวดเร็วดังกล่าวในฟอรั่มอื่น ๆ :) ขอขอบคุณคำสั่งทำงานอย่างสมบูรณ์ :)
ไซ Jahanzaib

@SyedJahanzaib หากคำตอบนี้แก้ไขปัญหาของคุณโปรดสละเวลาสักครู่และยอมรับโดยคลิกที่เครื่องหมายถูกทางด้านซ้าย ที่จะทำเครื่องหมายคำถามว่าตอบแล้วและเป็นวิธีที่แสดงความขอบคุณในเว็บไซต์ Stack Exchange
terdon

ขอโทษฉันลืมทำเครื่องหมายคำตอบ และขอบคุณคนอื่น ๆ ทุกคนเช่นกันสำหรับช่วงเวลาอันมีค่าและการตอบกลับพวกเขาช่วยฉันด้วยในการเรียนรู้การบรรลุเป้าหมายด้วยวิธีการที่แตกต่างกัน :)
Syed Jahanzaib

@SyedJahanzaib ถึงแม้ว่าฉันจะได้รับตราที่ดีสำหรับคำตอบนี้ฉันคิดว่าแม่นยำมากขึ้นและครอบคลุมคือคำตอบของ terdon
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. เชลล์ (ช้ากว่า / มีประสิทธิภาพน้อยกว่ามาก)

    while read a b c; do echo "$a $((b + c))"; done < file
    

2
$2+=$3อาจจะน่ากลัวกว่า
123

@ User112638726 แน่นอนมันเป็น ขอบคุณ
terdon

3
คุณสามารถใช้งานได้awk '{$2+=$3}NF--'ดังนั้นยังไม่มีฟิลด์ว่าง 3 ห้อยอยู่ แม้ว่านั่นเป็นเพียงการตั้งค่าของฉันและมันก็คล้ายกับการโพสต์เป็นคำตอบด้วยตัวของมันเอง :)
123

1
@ User112638726 ตอนนี้ไม่มีใครเกิดขึ้นกับฉัน ขอบคุณมาก!
terdon

ฉันเขียนสิ่งนี้ให้คุณ หมายเหตุว่าไม่เพียง แต่sedจัดการอย่างใดที่จะเข้าใจทุ่ง - แม้จะกำหนดเขตข้อมูลในการบินและเขต w / ในเขต - แต่เป็นเห็นได้ชัดคือกรณีที่แนวคิดทั้งหมดของยูนิกซ์ regexp ที่ตรงกันจริงตามหารสตริงเข้าไปในเขตตามรูปแบบ ! ใครจะรู้
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ในกรณีนี้ด้วยคำสั่งที่/อยู่(ซึ่งมักเป็นองค์ประกอบแรกของคำสั่ง ubstitution ใด ๆ)แต่เนื้อหาที่เหมือนกันจะถูกตีความโดย API พื้นฐานเพิ่มเติมเป็นชุดย่อยของที่ระบุไว้สำหรับฟังก์ชั่นในห้องสมุดมาตรฐาน C/sed s///regcomp()

ฉันสามารถทำให้งบการเงินนี้ได้อย่างมั่นใจเพราะsedเป็นไม่เพียงโปรแกรม แต่ค่อนข้างเรียบเรียงชื่อปฏิบัติการsedบนของ Unix เหมือนเครื่องเป็นการดำเนินงานของดีที่กำหนดก่อตั้งขึ้นในอดีตและมาตรฐานการควบคุมsed แอพลิเคชันของ regular- ระบบของฉัน ไลบรารีการจับคู่นิพจน์


จากsedสเป็ค:

sedยูทิลิตี้จะสนับสนุน Bres ที่อธิบายไว้ในนิพจน์ปกติ XBD พื้นฐาน ...

... ที่เราพบ ...

ทั้งสอง Bres และ Eres รับการสนับสนุนจากอินเตอร์เฟซการแสดงออกจับคู่ปกติในปริมาณที่ระบบการเชื่อมต่อของ POSIX.1-2008 ภายใต้regcomp(), regexec()และฟังก์ชั่นที่เกี่ยวข้อง

แอปพลิเคชันที่การโทรregcomp()จะแสดงสตริงรูปแบบและ ...

... [t] regcomp()ฟังก์ชั่นเขาจะรวบรวมการแสดงออกปกติที่มีอยู่ในสตริงที่ชี้ไปตามอาร์กิวเมนต์รูปแบบและวางผลลัพธ์ในโครงสร้างpreg ...

ในการดำเนินการดังกล่าวแอปพลิเคชันดังกล่าวจะอ้างถึงregcomp()ฟังก์ชั่นสหาย ...

... [t] regexec()ฟังก์ชั่นของเขาเปรียบเทียบสตริงที่สิ้นสุดด้วยค่า null ที่ระบุโดยสตริงที่มีการแสดงออกปกติpregรวบรวมที่เริ่มต้นโดยการเรียกก่อนหน้านี้ไปที่regcomp()...

... regexec()จะเติมองค์ประกอบของ [a] array ที่มีการชดเชย substrings ของสตริงที่สอดคล้องกับ\(subexpressions ที่อยู่ในวงเล็บ\)ของรูปแบบ ... patternตัวเองนับเป็น subexpression ...

... [t] เขาregexec()ทำงานต้องกรอกข้อมูลในทุกn ตรงกับองค์ประกอบของpmatchที่n ตรงกับที่และpmatchจัดทำโดยแอพลิเคชันแม้ว่าองค์ประกอบบางส่วนของpmatchไม่ตรงกับ subexpressions ในรูปแบบ


และเมื่อฉัน ...

/[^ ]* */

... sedก่อนจะคอมไพล์นิพจน์ปกติและเก็บผลลัพธ์ไว้ในหน่วยความจำหลังจากนั้นก็ใช้คอมไพล์ออโตเมติกที่เก็บไว้ที่นั่นกับเนื้อหาของ pattern-space ของฉันหลาย ๆ ครั้งตามที่จำเป็นเพื่อทำให้คำสั่งของฉันสำเร็จ เวลามันจะส่งผลให้ทุกคนเป็นอาร์เรย์ของหนึ่งหรือมากกว่าโมฆะคั่นเขตregexec()เป็นที่คั่นที่ชดเชยที่ส่งกลับโดย

และเมื่อฉันทำ ...

//

... เพื่อระบุว่าควรใช้นิพจน์ทั่วไปที่กำหนดไว้ล่าสุดsedเพียงแค่สามารถเรียกregexec()ใช้นิพจน์ปกติที่คอมไพล์แล้วอีกครั้ง แต่อาจใช้ในครั้งนี้กับอาร์กิวเมนต์สตริงที่เปลี่ยนแปลงหรือใช้พารามิเตอร์nmatchใหม่เป็นคำสั่ง I

โดยเฉพาะอย่างยิ่งยังคง ...

  • 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
    • Print และป๊อปอัพด้านบนของสแต็ค
  • 5000
    • ดันตัวเลข5000ไปที่ด้านบนสุดของสแต็กและดันองค์ประกอบทั้งหมดที่อยู่ในสแต็ก(ตอนนี้ไม่มี)ลงทีละหนึ่ง
  • 1000
    • เหมือนกัน แต่คราวนี้หมายเลข 5000 ที่ด้านบนสุดของสแต็กหลักถูกผลักลงหนึ่งและกลายเป็นองค์ประกอบที่สองในสแต็ก
  • +
    • เพิ่มตัวเลขสองอันดับแรกลงบนสแต็กเข้าด้วยกันแล้วนำทั้งสองเหล่านั้นออกจากสแต็กแล้วดันยอดรวมลงบนสุดของสแต็ก
    • ซึ่งส่งผลให้สแต็กประกอบด้วยจำนวน6000เท่านั้น
    • นี้เป็นข้อผิดพลาดทางไวยากรณ์ถ้าทั้งสององค์ประกอบในกองเป็นสตริง[]
  • p
    • pรีดด้านบนของสแต็กตามด้วย\newline ที่ต่อท้ายโดยไม่ต้อง popping จากด้านบนของสแต็ก
  • c
    • cบซ้อน

ฉันเชื่อว่าใช้งานได้ แต่ฉันแยกไม่ออก โดยรวมแล้วคุณกำลังตั้งค่าเพิ่มเติมสำหรับ dc รูปแบบแรกเหมาะสม ฉันคิดว่ามันตรงกับวันที่และช่องว่างต่อท้าย แต่ฉันไม่ได้สิ่งที่ใส่ไว้ในวงเล็บคลาสอักขระ ([&]) มันคงจะดีถ้าคุณสะกดคำนี้ออกมา
โจ

1
@Joe - ดีกว่าไหม
mikeserv

ว้าว! นั่นทำให้รู้สึกมากขึ้น (และแสดงให้ฉันเห็นสิ่งต่าง ๆ ที่ฉันต้องเรียนรู้เพิ่มเติม) โดยเฉพาะฉันไม่เคยสังเกตเห็นการใช้ // เพื่อนำรูปแบบปัจจุบันกลับมาใช้ใหม่ นั่นคือสิ่งที่คุณอ่านและลืมจนกว่าคุณจะพบตัวอย่างจริง ขอบคุณมาก. มันทำให้ฉันหัวเราะเพื่อดูว่าพลังสามารถบรรจุลงในคำสั่ง miniscule และใช้อธิบายเท่าใด
Joe

@ Joe - ดี ... บางทีฉันไปลงน้ำเล็กน้อย ...
mikeserv
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.