รวมไฟล์โดยใช้คอลัมน์ทั่วไป


8

ฉันมีไฟล์สองไฟล์ซึ่งฉันต้องการสร้างไฟล์ที่สามซึ่งมีข้อมูลทั้งหมด

ไฟล์ 1:

a 111 
b 222 
c 333 
d 666 
e 777 

ไฟล์ 2:

111 x1  
222 x2
333 x3
444 x4 
555 x5 
666 x6 
777 x7 
888 x8

ฉันต้องการรวมพวกเขาดังต่อไปนี้:

111  x1  a
222  x2  b
333  x3  c
444  x4  0
555  x5  0
666  x6  d
777  x7  e
888  x8  0

บันทึก:

คอลัมน์ที่สองของไฟล์ 1 เป็นชุดย่อยของคอลัมน์แรกของไฟล์ 2

คำตอบ:


7

joinคำสั่งไม่เกือบสิ่งที่คุณต้องการถ้าไฟล์จะถูกเรียงลำดับในขณะที่ตัวอย่างของคุณ:

join -12 -a2 file1 file2 -o2.1,2.2,1.1

คุณเพียงแค่ต้องเพิ่มเลขศูนย์ไปยังบรรทัดที่ไม่มีการแข่งขัน คุณสามารถใช้-eสวิตช์เพื่อ:

join -12 -a2 file1 file2  -o2.1,2.2,1.1 -e0

ถ้าคุณเพิ่ม-e0ไม่จำเป็นต้อง Perl :)
LilloX

@LilloX: จริงขอบคุณ ฉันพยายามแล้ว แต่ล้มเหลว (พิมพ์ผิด)
choroba

13

ใช้เข้าร่วม:

join -1 1 -2 2 -a1 -e0 -o'0,1.2,2.1' file2 file1

คำสั่ง join เข้าร่วมบรรทัดของสองไฟล์ซึ่งแบ่งใช้ฟิลด์ทั่วไปของข้อมูล ในกรณีนี้: เข้าร่วม file2 และ file1 โดยใช้ฟิลด์ 1 ( -1 1) ของ file2 และฟิลด์ 2 ( -2 2) ของ file1

ผลลัพธ์จะเป็น: "เขตข้อมูลที่เข้าร่วมเขต 2 ของไฟล์ 2, ฟิลด์ 1 ของไฟล์ 1" ( -o'0,1.2,2.1') หากมีฟิลด์ที่ขาดหายไปให้ใส่ 0 ( -e0)

หากหนึ่งในสองไฟล์มีเร็กคอร์ดมากกว่านั้นให้เพิ่ม (ในกรณีนี้ file2) ( -a1)

โปรดดู manpage ของคำสั่งเข้าร่วม


ดี. คุณสามารถเพิ่มคำอธิบายเล็กน้อยได้ไหม?
Lety

แน่นอนว่าได้รับการอัปเดต :)
LilloX

5

awkเวทมนตร์เล็กน้อย:

awk 'FNR==NR{a[$2]=$1;next}{if(a[$1]==""){a[$1]=0}; \
    printf "%s%s%s%s%s\n",$1,FS,$2,FS,a[$1]}' \
    file1 file2

หรือ

awk 'FNR==NR{a[$2]=$1;next}{if(a[$1]==""){a[$1]=0};
    print $1,$2,a[$1]}' file1 file2

เอาท์พุต

111 x1 a
222 x2 b
333 x3 c
444 x4 0
555 x5 0
666 x6 d
777 x7 e
888 x8 0

คำอธิบาย

  • FNR==NR{a[$2]=$1;next}

    รันบนfile1( FNR==NR) และสร้างโครงสร้างคีย์ - ค่า กุญแจสำคัญคือคอลัมน์ที่สอง ( $2) ของfile1, ค่าคือคอลัมน์แรก ( $1) ของfile1

  • {if(a[$1]==""){a[$1]=0};print $1,$2,a[$1]}

    วิ่งไปfile2และ

    • if(a[$1]==""){a[$1]=0}

      หากคีย์ในคอลัมน์แรก ( $1) file2ไม่มีอยู่file1เราจำเป็นต้องมี0

    • print $1,$2,a[$1]

      พิมพ์ (โดยใช้print) คอลัมน์แรกและคอลัมน์ที่สองของfile2และค่าของโครงสร้างคีย์ - ค่าด้วยคีย์ของคอลัมน์แรก ( $1) ของfile2

      หรือ

    • printf "%s%s%s%s%s\n",$1,FS,$2,FS,a[$1]}'

      พิมพ์ (ใช้printf) ครั้งแรกและคอลัมน์ที่สองของfile2และความคุ้มค่าของโครงสร้างค่าคีย์ที่มีคีย์ของคอลัมน์แรก (คน$1) file2ของ

      • FS เป็นตัวคั่นระหว่างคอลัมน์ที่นำมาจากไฟล์อินพุต

      • "%s%s%s%s%s\n"

        เป็นรูปแบบสำหรับการส่งออก

        • %s - สตริง

        • \n - ขึ้นบรรทัดใหม่


คุณอธิบายรหัสได้หรือไม่
gforce89

แน่นอนว่าคำตอบอัพเดทแล้ว
AB

1

ใช้q :

$ q "select f2.c1, f2.c2, ifnull(f1.c1,0) from file_2.txt f2 LEFT JOIN file_1.txt f1 on f1.c2 = f2.c1 "
111 x1 a
222 x2 b
333 x3 c
444 x4 0
555 x5 0
666 x6 d
777 x7 e
888 x8 0

บางครั้งมันอาจอ่านได้มากกว่านี้


1
สำหรับทุกคนที่สงสัยqอยู่ในแพ็คเกจpython3-q-text-as-data(Python 3) และในแพ็คเกจpython-q-text-as-data(Python 2)
kos

ขอบคุณ แต่ฉันจะหาqแพ็คเกจนี้ได้ที่ไหน ฉันดูเหมือนจะไม่สามารถติดตั้งอย่างใดอย่างหนึ่งหรือpython-q-text-as-data python3-q-text-as-data"E: ไม่พบแพคเกจ python3-q-text-as-data" ระบบของฉันแล้วมีการติดตั้งpython, python2.7, และpython3 python3.4
Paddy Landau

บางทีแพ็คเกจนี้ใหม่เกินไปและไม่พร้อมใช้งานในการเผยแพร่การแจกจ่ายของคุณ คุณสามารถโคลนได้ Github: github.com/harelba/q
Vi
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.