2009-06-24 31 views
134

Tôi có một dữ liệu với định dạng sau:Unix Sắp xếp với Tab Delimiter

foo<tab>1.00<space>1.33<space>2.00<tab>3 

Bây giờ tôi cố gắng sắp xếp các tập tin dựa trên các lĩnh vực cuối cùng giảm dần. Tôi đã thử các lệnh sau nhưng chưa được sắp xếp như chúng tôi mong đợi.

$ sort -k3nr file.txt # apparently this sort by space as delimiter 

$ sort -t"\t" -k3nr file.txt 
    sort: multi-character tab `\\t' 

$ sort -t "`/bin/echo '\t'`" -k3,3nr file.txt 
    sort: multi-character tab `\\t' 

Cách thích hợp để làm điều đó là gì?

Đây là sample data.

Trả lời

242

Sử dụng bash, điều này sẽ làm các trick:

$ sort -t$'\t' -k3 -nr file.txt 

Chú ý các ký hiệu đô la ở phía trước của chuỗi đơn trích dẫn. Bạn có thể đọc khoảng trong số ANSI-C Quoting sections of the bash man page.

+0

[Sử dụng] (https://stackoverflow.com/a/1250279/4970442) ''"' "'' để sử dụng nó bên trong một bí danh. –

+0

bạn có thể chỉ ra cách vượt qua dấu phân cách này để sắp xếp trong lệnh awk không? như trong 'awk' {print $ 0 | "sort -nr"> "outfile"} 'datafile', ngoại trừ với dấu phân cách tab thoát được gửi đến lệnh sắp xếp. – Merlin

1

tô nó qua một cái gì đó như awk '{ print print $1"\t"$2"\t"$3"\t"$4"\t"$5 }'. Điều này sẽ thay đổi không gian cho các tab.

+0

@MB: Tôi cần giữ nguyên không gian. – neversaint

+1

Chắc chắn là một cách sạch hơn để làm điều đó, nhưng không có gì ngăn cản bạn thoát khỏi đường ống, thay đổi không gian thành các tab, phân loại dữ liệu và sau đó chuyển nó qua lại một lần nữa, thay đổi các tab trở lại không gian. –

+1

Điều này sẽ không hoạt động nếu có một hỗn hợp các tab và dấu cách mà bạn muốn giữ lại. –

9

Theo mặc định dấu phân tách trường không được để trống để chuyển tiếp trống nên tab sẽ hoạt động tốt.

Tuy nhiên, các cột được lập chỉ mục cơ sở 1 và cơ sở 0, do đó bạn có thể muốn

sort -k4nr file.txt 

để sắp xếp file.txt theo cột 4 bằng số theo thứ tự ngược. (Mặc dù dữ liệu trong câu hỏi có 5 trường, vì vậy trường cuối cùng sẽ là chỉ mục 5.)

+4

Điều này sẽ chỉ hoạt động nếu số ký tự khoảng cách giữa các trường được phân cách bằng tab giống nhau đối với tất cả các dòng đầu vào. –

1

Dữ liệu lưu giữ chung như thế này không phải là điều tuyệt vời nếu bạn có thể tránh, vì mọi người luôn gây nhầm lẫn và không gian.

Giải quyết vấn đề của bạn rất đơn giản trong ngôn ngữ kịch bản như Perl, Python hoặc Ruby. Dưới đây là một số mã ví dụ:

#!/usr/bin/perl -w 

use strict; 

my $sort_field = 2; 
my $split_regex = qr{\s+}; 

my @data; 
push @data, "7 8\t 9"; 
push @data, "4 5\t 6"; 
push @data, "1 2\t 3"; 

my @sorted_data = 
    map { $_->[1] } 
    sort { $a->[0] <=> $b->[0] } 
    map { [ (split $split_regex, $_)[$sort_field], $_ ] } 
    @data; 

print "unsorted\n"; 
print join "\n", @data, "\n"; 
print "sorted by $sort_field, lines split by $split_regex\n"; 
print join "\n", @sorted_data, "\n"; 
2

Giải pháp $ không có tác dụng đối với tôi. Tuy nhiên, Bằng cách thực sự đặt ký tự tab trong lệnh: sắp xếp -t '' -k2

+0

Sử dụng ' 'để chèn tab trong trường hợp phím tab được sử dụng để tự động hoàn thành trong trình bao của bạn. –

1

Tôi muốn một giải pháp cho Gnu sắp xếp trên Windows, nhưng không có giải pháp nào trên đây hoạt động trên dòng lệnh .

Sử dụng đầu mối của Lloyd, tệp lô sau (.bat) đã hoạt động đối với tôi.

Nhập ký tự tab trong dấu ngoặc kép.

C:\>cat foo.bat 

sort -k3 -t" " tabfile.txt 
+1

Vâng, mẹo ở đây là đặt nó vào một tệp .bat, nếu không nó sẽ không hoạt động –

0

Tôi gặp sự cố này khi sắp xếp trong Cygwin trong bash shell khi sử dụng 'chung-số-loại'. Nếu tôi chỉ định -t$'\t' -kFg, trong đó F là số trường, nó không hoạt động, nhưng khi tôi đã chỉ định cả -t$'\t'-kF,Fg (ví dụ: -k7,7g cho trường thứ 7) thì nó đã hoạt động. -kF,Fg không có -t$'\t' không hoạt động.

3

Bạn cần phải đặt một ký tự tab thực tế sau -t -t và để làm điều đó trong một vỏ bạn nhấn ctrl-v và sau đó là ký tự tab. Hầu hết các trình bao mà tôi đã sử dụng đều hỗ trợ chế độ này của mục nhập chữ.

Hãy cẩn thận, tuy nhiên, vì sao chép và dán từ một địa điểm khác thường không giữ được các tab.

Các vấn đề liên quan