So sánh cạnh nhau của hơn hai tệp chứa giá trị số


8

Tôi có ba tệp chứa một dãy số được sắp xếp, mỗi tệp một dòng:

tập tin1

1
2
3

tập tin2

1
3
4

tập tin3

1
5

Tôi muốn "căn chỉnh" ba tệp này cạnh nhau như sau:

file1  file2  file3
1      1      1
2      
3      3
       4
              5

Tôi đã thử với sdiffnhưng nó chỉ hoạt động với 2 tệp


Bạn có kiểm tra diff3không?
Costas

@Costas diff3không có định dạng đầu ra đó.
Kusalananda

@Costas Có, tôi đã thử nghiệm diff3và như @Kusalananda đã tuyên bố chính xác, nó không tạo ra đầu ra đó. Ngoài ra, tôi đang tìm kiếm một giải pháp chung (cho n tệp, n> 2)
cheseaux

Nếu bạn so sánh từng dòng tại sao lại 5ở dòng thứ năm trong kết quả thay vì thứ ba?
Costas

Tôi không so sánh từng dòng
cheseaux 11/07/2016

Câu trả lời:


6

Bạn có thể xử lý từng tệp và in một dòng với một số ký tự, ví dụ như Xcho mỗi số bị thiếu trong chuỗi 1- max (trong đó max là số cuối cùng trong tệp đó), pastekết quả sau đó thay thế ký tự đó bằng khoảng trắng:

paste \
<(awk 'BEGIN{n=1};{while (n<$1) {print "X";n++}};{n=$1+1};1' file1) \
<(awk 'BEGIN{n=1};{while (n<$1) {print "X";n++}};{n=$1+1};1' file2) \
<(awk 'BEGIN{n=1};{while (n<$1) {print "X";n++}};{n=$1+1};1' file3) \
| tr X ' '

Nếu một giá trị nhất định bị thiếu trong tất cả các tệp, bạn sẽ nhận được các dòng trống trong đầu ra của mình (thực ra chúng không trống, chúng chỉ chứa các khoảng trống).
Để loại bỏ chúng thay thế tr X ' ' bằng sed '/[[:digit:]]/!d;s/X/ /g' Ngoài ra, nếu bạn cần một tiêu đề, trước tiên bạn luôn có thể chạy một cái gì đó như thế này:

 printf '\t%s' file1 file2 file3 | cut -c2-

Tôi đã có một thời gian khó khăn để tìm ra ;1phần cuối cùng có nghĩa là gì. Tôi đang sử dụng {print $0}thay vào đó, IMHO ít khó hiểu hơn một chút. Dù sao, cảm ơn một lần nữa
cheseaux

5

Một giải pháp chung với awk: yêu cầu GNU awk

gawk -v level=0 '
    FNR==1 {level++; head[level]=FILENAME}
    !seen[$1]++ { n++; idx[$1] = n }
    { out[idx[$1]][level] = $1 }
    END {
        for (j=1; j<=level; j++) {
            printf "%s\t", head[j]
        }
        print ""
        for (i=1; i<=n; i++) {
            for (j=1; j<=level; j++) {
                printf "%s\t", out[i][j]
            }
            print ""
        }
    }
' file{1,2,3,4}
file1   file2   file3   file4   
1   1   1       
2           2   
3   3           
    4       4   
        5       
            6   

Thực hiện một cách tiếp cận khác và đơn giản hơn dựa trên nhận xét của Don:

gawk '
    FNR==1 { printf "%s\t", FILENAME }
    { seen[$1][FILENAME] = $1 } 
    END {
        print ""
        PROCINFO["sorted_in"]="@ind_num_asc"
        for (i in seen) {
            for (j=1; j<=ARGC; j++) {
                printf "%s\t", seen[i][ARGV[j]]
            } 
            print ""
        }
    }
' file{1,2,3,4}
file1   file2   file3   file4       
    1   1           
            2       
3   3               
    4       4       
5       5           
            6       
7                   

Hiểu rồi. Trả lời cập nhật
glenn jackman

3

Một giải pháp với bash, join, paste, và hương vị xấu:

#! /usr/bin/env bash

if [ $# -lt 3 ]; then exit 1; fi

files=( '' "$@" )

declare -a temps
for ((i=0; i<=$#; i++)); do
    [ $i -eq 0 -o -f "${files[$i]}" ] || exit 1
    temps[$i]=$( mktemp -t "${0##*/}"_$$_XXXXXXXX ) || exit 1
done
trap 'rm -f "${temps[@]}"' EXIT HUP INT QUIT TERM

cat "$@" | sort -u >"${temps[0]}"

TAB=$( printf '\t' )
for ((i=1; i<=$#; i++)); do
    join -j1 -a1 -t"$TAB" "${temps[0]}" <(paste "${files[$i]}" "${files[$i]}") | \
        sed "/^[^$TAB]\$/ s/\$/$TAB/" >"${temps[$i]}"
done

printf '%s' ${files[1]}
for ((i=2; i<=$#; i++)); do
    printf '\t%s' ${files[$i]}
    let j=i-1
    let k=i-2
    join -j1 -t"$TAB" "${temps[$j]}" "${temps[$i]}" >"${temps[$k]}"
    cat "${temps[$k]}" >"${temps[$i]}"
done
printf '\n'

cut -d "$TAB" -f 2- <"${temps[$#]}" | sort -n

Ngoại trừ cái cuối cùng sort -n, tất cả những thứ này hoạt động với bất kỳ mục văn bản nào thay vì số, miễn là các mục đó không chứa các tab (nhưng TABcó thể được thay đổi thành bất kỳ dấu tách nào khác). Ngoài ra, nó có thể được thực hiện chỉ với 3 tệp tạm thời và một số thứ xáo trộn xung quanh (nhưng điều đó sẽ làm tăng mùi vị xấu).

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.