การเพิ่มคอลัมน์ของค่าในไฟล์ที่คั่นด้วยแท็บ


17

ฉันจะเพิ่มคอลัมน์ของค่าในไฟล์ที่มีจำนวนแถวที่แน่นอนได้อย่างไร ฉันมีไฟล์อินพุตดังนี้:

ไฟล์อินพุต:

SPATA17 1   217947738
LYPLAL1 1   219383905
FAM47E  4   77192838
SHROOM3 4   77660162
SHROOM3 4   77660731
SHROOM3 4   77662248

ไฟล์ที่ส่งออก:

SPATA17 1   217947738 file1
LYPLAL1 1   219383905 file1
FAM47E  4   77192838  file1
SHROOM3 4   77660162  file1
SHROOM3 4   77660731  file1
SHROOM3 4   77662248  file1

ในกรณีนี้ฉันต้องการเพิ่มคอลัมน์ของค่าจนถึงจำนวนแถวในไฟล์ค่ายังคงสอดคล้องเช่น "file1"

เหตุผลคือฉันมี 100 ไฟล์เหล่านั้นฉันไม่ต้องการเปิดแต่ละไฟล์และวางคอลัมน์ นอกจากนี้ยังมีวิธีการทำให้เป็นอัตโนมัติโดยไปที่ไดเรกทอรีและเพิ่มคอลัมน์ของค่า ค่ามาจากชื่อไฟล์ซึ่งจะต้องเพิ่มในแต่ละแถวของไฟล์ในคอลัมน์สุดท้าย / แรก

คำตอบ:


22

คุณสามารถใช้ลูปซับเดียวดังนี้:

for f in file1 file2 file3; do sed -i "s/$/\t$f/" $f; done

สำหรับแต่ละไฟล์ในรายการสิ่งนี้จะใช้sedต่อท้ายแท็บและชื่อไฟล์แต่ละบรรทัด

คำอธิบาย:

  • การใช้-iแฟล็กด้วยsedเพื่อทำการแทนที่, เขียนทับไฟล์
  • s/PATTERN/REPLACEMENT/ดำเนินการทดแทนด้วย ในตัวอย่างนี้ PATTERN คือ$จุดสิ้นสุดของบรรทัดและ REPLACEMENT คือ\t(= a TAB) และ$fเป็นชื่อไฟล์จากตัวแปร loop s///คำสั่งอยู่ในราคาสองครั้งเพื่อให้เปลือกสามารถขยายตัวแปร

รหัสใช้งานได้คุณอธิบายเนื้อหาภายในเครื่องหมายคำพูดได้หรือไม่
Ron

เช่นเดียวกับ "awk" ที่ใช้ขณะทำงานกับคอลัมน์คือ 'sed' ยังใช้สำหรับสถานการณ์ที่คล้ายกันด้วยฉันเป็นมือใหม่ที่ 'awk' และ 'sed'
Ron

@Ron sedเป็นประโยชน์มากที่สุดสำหรับการทดแทนรูปแบบและการบันทึกในสถานที่ สำหรับความต้องการของคุณในการบันทึกไฟล์มันเป็นตัวเลือกที่ค่อนข้างสะดวก หากคุณไม่จำเป็นต้องเขียนกลับไปที่ไฟล์เดียวกันกับที่คุณกำลังดำเนินการawkอยู่โดยทั่วไปแล้วจะง่ายกว่ามากในการทำงานกับ
janos

ส่วนตัวผมได้รับการดีดกลับขึ้นมาawkของอินพุต / เอาต์พุตแยกสนามบ่อยเกินไปและจึงพยายามที่จะหลีกเลี่ยงการใช้เมื่อใดก็ตามที่เป็นไปได้ที่ทำให้sedสนใจมากขึ้น
user5359531

11

มาทำไมพวกคุณแนะนำเครื่องมือที่ทรงพลังเหล่านั้นเมื่อมีpasteคำสั่ง!

$ cat a
A
B
C
D
$ cat b
1
2
3
4
$ paste a b
A   1
B   2
C   3
D   4

ด้วยเล่ห์เหลี่ยมเล็กน้อยคุณสามารถใช้pasteเพื่อวัตถุประสงค์ของ OP อย่างไรก็ตามจะไม่แทนที่ไฟล์ inplace:

for f in file1 file2 file3; do 
    paste $f <(yes $f | head -n $(cat $f | wc -l)) > $f.new
done

วิธีนี้จะวางชื่อไฟล์ที่เกี่ยวข้องเป็นคอลัมน์สุดท้ายของแต่ละไฟล์ลงในไฟล์ใหม่ filename.new


ขอบคุณ! pasteเป็นอัญมณีที่ซ่อนเร้นแน่นอน
neu242

10

คุณสามารถใช้awk:

awk '{print $0, FILENAME}' file1 file2 file3 ...

เนื่องจากแต่ละไฟล์มีชื่อแตกต่างกันดังนั้นฉันต้องทำอย่างนี้ 100 ครั้งมีวิธีทำครั้งเดียวไหม?
Ron

ไม่FILENAMEเป็นตัวแปรในawkซึ่งจะขยายเป็นชื่อไฟล์ปัจจุบันที่awkกำลังประมวลผล awkคุณเพียงแค่ทำมันเป็นหนึ่งในอาหารไฟล์ทั้งหมดไป
cuonglm

ตกลง แต่จะนำเอาต์พุตไปยังไฟล์ใหม่ของแต่ละไฟล์ได้อย่างไร awk จะจัดเก็บแต่ละไฟล์ขณะประมวลผลหรือไม่
Ron

หากคุณมีGNU awk 4.1.0หรือใหม่กว่าคุณสามารถใช้-iเพื่อแก้ไข inplace มิฉะนั้นคุณควรเปลี่ยนเส้นทางawkouput ไปที่ไฟล์ temp จากนั้นใช้grepเพื่อแยกบรรทัดจากแต่ละไฟล์
cuonglm

คุณสามารถทำได้for file in *; do awk 'BEGIN{OFS="\t"}{print $0, FILENAME}' $file; done
fedorqui
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.