Kết hợp và dán vào dòng


7

Vì vậy, tôi có 2 tệp văn bản rất lớn, bao gồm các dòng như vậy:

Đầu tiên:

Robert:Dillain:Other:Other:Other
Julian:Brude:Other:Other:Other
Megan:Flikk:Other:Other:Other
Samantha:Minot:Other:Other:Other
Jesus:Kimmel:Other:Other:Other

Thứ hai:

Sb:Minot:amsen
Jbb:Kimmel:verlin
R:Dillain:bodent
Mb:Flikk:kentin
Jb:Brude:kemin

Tôi muốn ghép cả hai theo cột thứ hai (Dillain, Brude, v.v.) và dán chúng vào các dòng như vậy:

ĐẦU RA:

Robert:Dillain:Other:Other:Other:R:Dillain:bodent
Jesus:Kimmel:Other:Other:Other:Jbb:Kimmel:verlin
Samantha:Minot:Other:Other:Other:Sb:Minot:amsen
etc...
etc...

Tôi đã nghĩ đến việc sử dụng sedcho việc này, nhưng mọi thứ dựa trên Unix sẽ rất tuyệt. Tôi đã không có may mắn khi cố gắng tự mình tìm ra cách để làm điều này.


Thứ tự bản ghi đầu ra của bạn dường như không tuân theo một trong hai tệp đầu vào - điều đó có đáng kể không?
Steeldo

Ý bạn thế nào bạn có nghĩa là nó dường như không phải là đầu ra mong muốn? Vì nó trông giống như vậy nhưng tôi có thể đã bỏ lỡ điều gì đó
dùng104391

tất cả các dòng chắc chắn sẽ cặp?
mikeerv

Câu trả lời:


8

Điều này nghe có vẻ như một nhiệm vụ cho join:

join -t":" -o "1.1,1.2,1.3,1.4,1.5,2.1,2.2,2.3" \
   -j 2 <(sort -k2,2 -t: test1) <(sort -k2,2 -t: test2)

Đầu ra:

Julian:Brude:Other:Other:Other:Jb:Brude:kemin
Robert:Dillain:Other:Other:Other:R:Dillain:bodent
Megan:Flikk:Other:Other:Other:Mb:Flikk:kentin
Jesus:Kimmel:Other:Other:Other:Jbb:Kimmel:verlin
Samantha:Minot:Other:Other:Other:Sb:Minot:amsen

Phá vỡ:

  • -t đặt dấu phân cách trường thành :
  • -o đặt định dạng in
  • -j tham gia vào số cột 2
  • <(sort -k2,2 -t: file)sắp xếp trước tập tin theo -kcột thứ hai -tđặt dấu phân cách trường thành:

1
@mikeerv Điểm tốt. Tôi đã cập nhật nó với -k2,2. Vâng joinlà một công cụ hữu ích thú vị mà hầu hết có xu hướng quên là trên hệ thống - (tôi biết là tôi làm), vì không phải ngày nào tôi cũng cần phải nối 2 tệp lại với nhau. Tôi có xu hướng sử dụng jointhường xuyên như có nhật thực. lol
devnull

5

Đây là nhiệm vụ đơn giản cho awk:

awk -F':' -vOFS=':' 'NR==FNR{a[$2]=$0;next}{print $0,a[$2]}' file2 file1

Đầu tiên chúng ta đặt :làm dấu tách trường cho cả đầu vào (với -F) và đầu ra (với OFS) sau đó nếu tệp đầu tiên được xử lý ( file2) chúng ta gán toàn bộ dòng cho phần tử bảng được lập chỉ mục với trường thứ hai. Khi tệp tiếp theo ( file1) được xử lý, chúng tôi sẽ in các dòng của nó thêm dòng từ tệp trước đó được lưu trữ a[$2]).


2

Với sedbạn có lẽ có thể làm:

sed 's|[^:]*:\([^:]*\).*|/^[^:]*:\1:/s/$/:&/;t|' file2 | sed -f - file1

... sẽ liên quan đến một sedquá trình đọc tệp thứ hai và viết một sedtập lệnh để chỉnh sửa tập đầu tiên thành sedstdin thứ hai . Gần như tôi có thể nói với bạn rằng bạn không nên có bất kỳ vấn đề gì với việc trực tiếp đưa nội dung nguyên văn vào một biểu thức chính quy như thế. Nếu có khả năng có các ký tự meta trong đầu vào, có rất nhiều câu trả lời trên trang web này trong đó thảo luận về phương tiện thoát khỏi chúng. Tuy nhiên, nếu có thể được yêu cầu, thì những điều sau đây là đủ:

sed 's|[]&\./*[]|\\&|g;s|...' ... | sed -f - file1

Tuy nhiên, có lẽ cùng tên joinlà giải pháp tốt hơn - đây chỉ là để chứng minh làm thế nào để làm điều đó với sedvì bạn đã đề cập đến nó.

Dù sao, tập lệnh thứ hai sedáp dụng cho file1kết thúc giống như (với một dòng tương tự như bên dưới cho mỗi dòng trong tệp2) :

/^[^:]*:Dillain:/s/$/:R:Dillain:bodent/;t

... có nghĩa là nếu nó gặp một dòng khớp với Dillain cho trường được phân cách bằng dấu hai chấm thứ hai, thì nó sẽ nối thêm chuỗi : R: Dillain: bodent vào đuôi của nó. Bởi vì có lẽ không có ý nghĩa gì trong việc tiếp tục cố gắng khớp một dòng trong file1khi một dòng từ file2đã được nối thêm, tlệnh esting trailing chỉ phân nhánh bất kỳ sự thay thế thành công nào ngay khi nó hoàn thành.


Kỳ dị. Tôi đã được trao awkhuy hiệu thẻ cho việc này: Tôi thậm chí không biết cách sử dụng awk.
mikeerv

0

Qua trăn3

#!/usr/bin/python3
import csv
import sys
file1, file2 = sys.argv[1], sys.argv[2]
with open(file2) as second, open(file1) as first:
    second_list = second.readlines()
    first_list = first.readlines()
for line1 in first_list:
    for line2 in second_list:
        if line1.split(':')[1] == line2.split(':')[1]:
            print(line1.strip()+line2.strip())

Sao chép và dán đoạn script trên vào một tệp có tên script.py. Và sau đó chạy tập lệnh bằng cách chạy lệnh dưới đây trên thiết bị đầu cuối.

python3 script.py file1 file2
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.