Sắp xếp một tệp được phân định bằng tab


180

Tôi có một dữ liệu với định dạng sau:

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

Bây giờ tôi đã cố gắng sắp xếp tệp dựa trên trường cuối cùng. Tôi đã thử các lệnh sau nhưng nó không được sắp xếp như chúng ta 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 đúng đắn để làm điều đó là gì?

Đây là dữ liệu mẫu .

Câu trả lời:


312

Sử dụng bash , điều này sẽ thực hiện thủ thuật:

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

Lưu ý ký hiệu đô la ở phía trước chuỗi trích dẫn đơn. Bạn có thể đọc về nó trong phần Trích dẫn ANSI-C của trang bash man .


2
Sử dụng '"'"' để sử dụng nó trong một bí danh.
Pablo A

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

11

Theo mặc định, dấu phân cách trường không trống để chuyển sang trống để tab 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 nên bạn có thể muốn

sort -k4nr file.txt

để sắp xếp file.txt theo cột 4 theo thứ tự ngược lại. (Mặc dù dữ liệu trong câu hỏi thậm chí có 5 trường nên 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ố lượng ký tự khoảng trắng giữa các trường được phân tách bằng tab là giống nhau cho tất cả các dòng đầu vào.
Lars Haugseth

5

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

Mặc dù vậy, hãy cẩn thận, vì sao chép và dán từ nơi khác thường không bảo quản các tab.


Đây là câu trả lời tốt nhất (di động nhất). emacs cũng cho phép bạn làm điều đó trong chế độ 'trích dẫn chèn': C-q <tab>chẳng hạn. Tôi nghĩ nó cũng ^Vở dạng nano.
Wyatt8740

3

Giải pháp $ không hiệu quả với tôi. Tuy nhiên, bằng cách thực sự đặt chính ký tự tab trong lệnh đã làm: sort -t '' -k2


1
Sử dụng <C-v><Tab>để 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.
Júda Ronén

1
Trích dẫn ANSI $'\t'hoạt động trong ksh, zsh và bash. Vỏ Bourne không hỗ trợ nó. Xem bài đăng này: unix.stackexchange.com/a/371873/201820
codeforester 20/03/18

1

ống nó thông 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 thành các tab.


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

1
Chắc chắn có một cách sạch hơn để làm điều đó, nhưng không có gì ngăn cản bạn chuyển nó qua awk, thay đổi khoảng trắng thành các tab, sắp xếp dữ liệu và sau đó chuyển nó qua awk một lần nữa, thay đổi các tab trở lại vào không gian.
Michiel Buddingh

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

1

Nói chung, việc giữ dữ liệu như thế này không phải là một điều tuyệt vời nếu bạn có thể tránh nó, bởi vì mọi người luôn nhầm lẫn giữa các tab và khoảng trắng.

Giải quyết vấn đề của bạn rất đơn giản trong một 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";

1

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

Sử dụng đầu mối của Lloyd, tệp bó sau (.bat) đã hoạt động 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à đưa nó vào một tệp .bat, nếu không nó sẽ không hoạt động
Carlos Rendon

1

Tôi đã gặp vấn đề này với việc sắp xếp trong cygwin trong bash shell khi sử dụng 'general-number-sort'. 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ả hai -t$'\t'-kF,Fg(ví dụ -k7,7gcho trường thứ 7) thì nó đã hoạt động. -kF,Fgkhông có -t$'\t'không hoạt động.


0

Nếu bạn muốn làm cho bản thân dễ dàng hơn bằng cách chỉ có các tab, hãy thay thế khoảng trắng bằng các tab:

tr " " "\t" < <file> | sort <options>

Tr của tôi không đọc tập tin, chỉ stream XD. usage: tr [-Ccsu] string1 string2
Mèo Unun

1
tr string1 string2 <some-file. Tất cả mọi thứ có thể đọc một tập tin miễn là nó có thể đọc stdin.
Randal Schwartz

0

Câu trả lời của Lars Haugseth chỉ hoạt động từ dòng lệnh cho tôi khi nó đưa ra lỗi này nếu được thực thi từ tập lệnh shell:

sắp xếp: tab nhiều ký tự '$ \ t'

Giải pháp nếu được mã hóa theo tập lệnh shell nếu ai đó đang tìm là

sort -t'    '

ký tự tab ở giữa trích dẫn.

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.