Cách đặt câu trên các dòng riêng biệt trên Linux


7

Tôi có một nhiệm vụ để đặt câu trong một tệp văn bản trên các dòng riêng biệt. Một cái gì đó như thế này gần như hoạt động:

cat file.txt | tr '.' '\n'

Nhưng tôi không muốn mất dấu chấm, dấu chấm hỏi và dấu chấm than từ câu của mình. Làm thế nào tôi có thể làm cho công việc này?


2
Vui lòng cho chúng tôi xem một ví dụ về tệp đầu vào của bạn và đầu ra mong muốn của bạn.
terdon

2
Bạn có lo lắng về ngắt dòng sau dấu chấm câu trong câu không? Ví dụ, từ viết tắt tiếng Latin (ví dụ, 'ví dụ'), câu trích dẫn (ví dụ như ' "Cái gì!", Họ kêu lên), ký hiệu (ví dụ, '3 là sáu'!.)
Charles Stewart

3
Đây là một điều rất khó để có được đúng. Bạn cần một trong hai để xác định phạm vi của câu hỏi nhiều hẹp hơn và chính xác, hoặc phát triển một chương trình mà thực sự có thể hiểu được tiếng Anh. Ba thách thức mà chưa có câu trả lời nào cho đến nay gặp phải: (1) Chữ viết tắt có thể được gắn với mã thông báo tiếp theo (từ / tên) hoặc mã trước đó . Đưa ra văn bản, tiến sĩ Dr. Oz sống ở Lakeside Tiến sĩ Phil là người vô gia cư. Thật khó để nhận ra rằng Phil Phil bắt đầu một câu mới. Tiết (Cont'd)
Scott

1
(Tiếp theo) Từ (2) Dấu ngoặc kép và dấu ngoặc đơn. He asked, “What should I bring?” She replied, “A bottle of wine would be nice.” Then she hung up.Hành vi đúng là để phá vỡ sau khi .hoặc ?. Tương tự như vậy, sử dụng awk. (Đó là tuân thủ POSIX.) Hoặc sử dụng mygawk., Trong đó bạn không cần phải ngắt giữa tuân thủ. và ")". (3) Đôi khi, ... ... xảy ra trong một câu. Ngoài ra, (4) Đưa ra văn bản, xông Oh! Tôi quên tắt bếp. Một số người có thể coi đây là một câu; "Oh!" rõ ràng không phải là một câu, vì nó không chứa chủ ngữ hay động từ. Nhưng đó là chủ quan.
Scott

Tôi thấy, ví dụ như trên thực tế , rằng Charles đã giải quyết một số điểm này. +1 cho Số n ! đại diện cho n giai thừa.
Scott

Câu trả lời:


16

Tôi không thể chắc chắn mà không thấy một ví dụ thực tế của dữ liệu của bạn nhưng những gì bạn đang có thể tìm kiếm được thêm một dòng mới sau mỗi lần xảy ra ., !?. Tôi không biết bạn muốn xử lý dấu chấm phẩy như thế nào ;vì chúng không thực sự đánh dấu kết thúc câu. Tùy bạn.

Dù sao, bạn có thể thử sed:

$ echo 'This is a sentence! And so is this. And this one?' | 
    sed 's/[.!?]  */&\n/g' 
This is a sentence! 
And so is this. 
And this one?

Đây s///là toán tử thay thế. Định dạng chung của nó là s/pat/replacementvà nó sẽ thay thế patbằng replacement. Các gcuối cùng làm cho nó chạy thay thế trên tất cả các lần xuất hiện của pat. Không có nó, nó sẽ dừng lại ở cái đầu tiên. Đây &là một sedcấu trúc đặc biệt có nghĩa là "bất cứ điều gì đã được khớp". Vì vậy, ở đây chúng ta đang thay thế bất kỳ ., !hoặc ?với bất cứ điều gì được kết hợp và một dòng mới.

Nếu văn bản của bạn có thể bao gồm các chữ viết tắt như e.g., bạn có thể chỉ muốn thay thế nếu chữ cái tiếp theo là VỐN:

$ echo 'This is a sentence! And so is this. And this one? Negative, i.e. no.' | sed 's/\([.!?]\) \([[:upper:]]\)/\1\n\2/g' 
This is a sentence!
And so is this.
And this one?
Negative, i.e. no.

Lưu ý rằng điều này sẽ không xử lý các câu như Dr. Jones said hello.chính xác vì nó sẽ cho rằng .sau khi Drxác định một câu cho rằng chữ cái tiếp theo được viết hoa. Tuy nhiên, chúng tôi hiện đang tiếp cận một mức độ phức tạp vượt xa định dạng Q & A đơn giản và thực sự đòi hỏi một trình phân tích cú pháp ngôn ngữ tự nhiên đầy đủ.


1
+1 để trở thành người trả lời đầu tiên cho (a) chụp (và loại bỏ) khoảng trắng sau dấu chấm câu và (b) bao gồm gở cuối (vì một câu ngắn có thể được chứa hoàn toàn trong một dòng, với các câu khác trước và sau). Nếu tôi có thể cho bạn +2, tôi sẽ có, nếu chỉ bạn nói (space)*- vì một số người trong chúng ta vẫn gõ theo cách chúng ta được dạy: tách câu với hai khoảng trắng. (Ngoài ra, nếu văn bản đầu vào là đầu ra của một cái gì đó như RUNOFF roff, hoặc nroff, các ký tự khoảng trắng thừa có thể được sử dụng để đạt được chứng minh văn bản.)
Scott

Chưa bao giờ nghe về khái niệm hai không gian đó, thú vị
TheBlastOne 18/03/2015

@Scott cảm ơn, và điểm rất tốt cho kết hợp space*, trả lời chỉnh sửa.
terdon

@don_crissti đúng, cảm ơn. Tôi đã thêm hai khoảng trắng với cái thứ hai là tùy chọn. Điều đó sẽ hoạt động miễn là một câu được viết đúng (với một khoảng trắng sau dấu chấm câu) và sẽ không thêm một dòng trống trừ khi có một khoảng trắng ở đầu vào.
terdon

2
@don_crissti chết tiệt, tôi thậm chí đã không xem xét viết tắt. Bạn có thể làm một cái gì đó giống như sed 's/\([.!?]\) \([[:upper:]]\)/\1\n\2/g'chỉ khớp nếu ký tự tiếp theo là chữ in hoa.
terdon

6

Thử:

sed -e :1 -e 's/\([.?!]\)[[:blank:]]\{1,\}\([^[:blank:]]\)/\1\
\2/;t1'

Trên một đầu vào như:

Sentence 1. Sentence 1.2? Sentence 2!? Sentence 3.
Sentence 4... Sentence 5.

Nó cho:

Sentence 1.
Sentence 1.2?
Sentence 2!?
Sentence 3.
Sentence 4...
Sentence 5.

(và là POSIX).


@mikeerv, không tôi nhắc lại trong khi nó khớp. Giống như thêm gcờ vào snhưng với sự bổ sung mà nó xử lý cả hai .s . . x.
Stéphane Chazelas

1
+1 cho [[:blank:]]\{1,\}, mặc dù sẽ rất tuyệt nếu bạn giải thích những gì bạn đang làm. Tôi hiểu điều đó, nhưng OP thừa nhận là một người mới.
Scott

2

Sử dụng sedthay thế:

sed 's/\./\.\n/' file.txt

1
Các câu không chỉ kết thúc khi dừng hoàn toàn. Ngoài ra, UUoC .
terdon

2

Nhiệm vụ có một số cạm bẫy. Một lựa chọn có thể là:

sed 's/\([.?!;]\) */\1\n/g' file.txt

Đây là thay thế các ký tự trong bộ ký tự đã cho ( [.?!;]thêm dấu hai chấm hoặc xóa dấu chấm phẩy phù hợp với nhu cầu của bạn) theo sau là khoảng trắng tùy chọn ( *) bằng ký tự được thay thế ( \1mở rộng cho khớp giữa \(\)) và một dòng mới ( \n).


Stephane, tôi nghĩ rằng bạn phải thêm \ngợi ý cho hầu hết các giải pháp được đăng ở đây. (Tôi đã chỉnh sửa \?cho *.)
Janis

+1 để là người trả lời đầu tiên sử dụng (space)*.
Scott

1

Thử:

awk -F. '{ for (i=1;i<=NF;i++) printf "%s.\n",$i ;} ' < input_file > output_file

Ở đâu

  • awk sử dụng .(dấu chấm) làm dấu phân cách,
  • và các vòng lặp cho mọi lĩnh vực, in dòng, chấm một dòng mới

Điều đó chỉ phù hợp với thời gian. Thế còn ?!? Ngoài ra, bạn cần tính đến khoảng trắng giữa khoảng thời gian và câu tiếp theo.
terdon

OP chỉ đề cập đến dấu chấm.
Archemar 18/03/2015

Không, họ không: ", tôi không muốn mất dấu chấm, dấu chấm hỏi và dấu chấm than từ câu của mình."
terdon

Bạn có ý nghĩa gì bởi "một dấu chấm một dòng mới"? "Một dấu chấm trên mỗi dòng mới"?
Peter Mortensen

1
@ Peter: Trong trường hợp các bạn chưa tìm này ra chưa, tôi nghi ngờ rằng Archemar có nghĩa là "in dòng, một dấu chấm , một dòng mới."
Scott

1

Có cuộc sống bên ngoài một lớp lót ...

Bộ chia câu không bao giờ sẵn sàng, luôn có thêm một chi tiết cần khắc phục: một máy đa năng Perl!

#!/usr/bin/perl

use strict;
my $pont=qr{[.!?]+};                   ## pontuation
my $abrev=qr{\b(?:Pr|Dr|Mr|[A-Z])\.};  ## abreviations

$/="";   

while(<>){ chomp;                      ## for each paragraph,

  s/\h*\n\h*/ /g;                      ## remove \n
  s/($pont)\h+(\S)/$1\n$2/g;           ## pontuation+space
  s/($abrev)\n/$1 /g;                  ## undo \n after abreviations

  print "$_\n\n";
}

vì vậy:

A single ‘-’ operand is not really an option ! It stands for
standard input. Or for standard output ? For example:
smth -’ reads from stdin; and is equal
to plain smth’... Could it appear as any operand that
requires a file name ? Certainly !

Robert L. Stevenson wrote  Dr. Jekyll and Mr. Hyde. Back in 12.12.1886

the end

đầu ra là:

A single ‘-’ operand is not really an option !
It stands for standard input.
Or for standard output ?
For example: smth -’ reads from stdin; and is equal to plain smth’...
Could it appear as any operand that requires a file name ?
Certainly !

Robert L. Stevenson wrote  Dr. Jekyll and Mr. Hyde.
Back in 12.12.1886

the end

Rất tốt! Bạn là người duy nhất đã tấn công vào vấn đề khó khăn của chữ viết tắt (ví dụ: Ông Mr. Spock '). Nhưng (1) Gần như không thể tạo ra một danh sách đầy đủ các chữ viết tắt kết thúc bằng một dấu chấm. Những người rõ ràng mà bạn đã bỏ lỡ bao gồm ăn thịt người Tôi không nhận ra được Pr Pr - bạn có dùng nó cho giáo sư không? Tiết (Cont'd)
Scott

(Tiếp theo) ... Một vài người khác bạn bỏ lỡ là cấp bậc quân sự (Gen, Col, Thiếu tá, đại úy, ...), “tiến sĩ” (số nhiều của “Tiến sĩ”, như trong “Ts. Oz và Phil”), hướng la bàn (N, S, E, W) , và không có nghĩa là không có nghĩa là Bắc Bắc hay Số Số. (2) Ngược lại, mã của bạn giả định rằng Tiến sĩ Tiến không bao giờ là kết thúc của một câu, vì vậy, Oak Oak St. trở thành Lakeside Dr. The Lake Chalet nằm bên phải bạn. Mùi được thể hiện như là Oak Oak St. // Ăn trở thành Lakeside Dr. Lake Lake nằm bên phải bạn. Tiết (Cont'd)
Scott

(Tiếp theo) Từ (3) Tương tự như vậy, nó giả định rằng một chữ cái không bao giờ có thể là từ cuối cùng của câu. Hãy xem xét, Ai đang đi? John và I. Khi nào? Ngày mai." Mã của bạn nghĩ rằng John John và I. Khi nào? là tất cả một câu. Tương tự như vậy, chữ cái thứ 17 của bảng chữ cái là Q. Chữ cái thứ 18 của bảng chữ cái là R. Tiết, Hồi Shakespeare đã viết một vở kịch về Henry V. Ghi Tiết Bạn đã nghe nói về Malcolm X chưa? Tiết chí (4) Xem thêm nhận xét của tôi về câu hỏi.
Scott

@Scott, cảm ơn bạn đã bình luận, báo cáo lỗi. Như tôi đã tuyên bố lúc đầu: họ không bao giờ sẵn sàng. Cách (dài) để đi là cố gắng tăng độ chính xác từng bước, biết rằng chúng ta còn cách xa 100%. SentSplitter của tôi cho tiếng Bồ Đào Nha có nhiều dòng hơn (bao gồm các tùy chọn để xử lý toán LaTex, trò chơi ký hiệu cờ vua, url, email, v.v.). Nhiệm vụ này rõ ràng cần kiểm tra, đánh giá, kỹ thuật học tập ..., đa chức năng, mô đun hóa, v.v.
JJoao 18/03/2015

-1
sed 's/\([.!?]  *\)\{0,1\}/\1\\/g' <infile | xargs printf %s\\n

Tôi đã có thứ này foldtrước đây - rất nhanh - nhưng tôi nhận ra rằng tôi có thể làm điều tương tự xargskhi phải xử lý đầu vào hoặc thực hiện bất kỳ sedvòng lặp nhánh nào nếu tôi thoát khỏi tất cả mọi thứ không phải là kết thúc char hoặc bất kỳ không gian tiếp theo.

Vì vậy, trong câu lệnh trên sedsẽ khớp chuỗi null hoặc chuỗi kết thúc cho mỗi ký tự (không phải trong chuỗi) xảy ra trong đầu vào. Ở phía bên phải sedthay thế chuỗi null hoặc chuỗi kết thúc trong \1và sau đó chèn dấu gạch chéo ngược. Kết quả là mỗi char nhưng một trong số .!?đó được theo sau bởi ít nhất một khoảng trắng được \thoát dấu gạch chéo ngược. Đây bao gồm các \newline rằng sedchèn sau mỗi lần thay khi nó ghi vào thiết bị xuất chuẩn.

Bởi vì xargssẽ hoàn toàn tạo ra một \newline thoát dấu gạch chéo ngược và sẽ phân chia các đối số mà nó trao cho tiện ích được đặt tên của nó trên các khoảng trắng không bị che giấu, printfkết thúc việc in tất cả các chuỗi giống như câu xargsđọc trong bất kỳ khoảng trống nào trên mỗi dòng. Hơn thế nữa - nó thực hiện theo từng đợt tiếp cận ARGMAXkích thước - càng nhiều càng tốt tại một thời điểm. Và tất nhiên sedcũng nên quản lý công việc của mình khá nhanh - nó chỉ phải thực hiện một thay thế toàn cầu cho mỗi dòng đầu vào.

Các kết quả diễn ra như thế này:

Một số Lorem Ipsum được lấy từ www.lipsum.com :

sed 's/\([.!?]  *\)\{0,1\}/\1\\/g' <<LIPSUM | xargs printf %s\\n
Section 1.10.32 of "de Finibus Bonorum et Mal
orum", written by Cicero in 45 BC
"Sed ut perspiciatis unde omnis iste natus er
ror sit voluptatem accusantium doloremque lau
dantium, totam rem aperiam, eaque ipsa quae a
b illo inventore veritatis et quasi architect
o beatae vitae dicta sunt explicabo.
Nemo enim ipsam voluptatem quia voluptas sit 
aspernatur aut odit aut fugit, sed quia conse
quuntur magni dolores eos qui ratione volupta
tem sequi nesciunt.
Neque porro quisquam est, qui dolorem ipsum q
uia dolor sit amet, consectetur, adipisci vel
it, sed quia non numquam eius modi tempora in
cidunt ut labore et dolore magnam aliquam qua
erat voluptatem.
Ut enim ad minima veniam, quis     ...
...
reiciendis voluptatibus maiores alias consequ
atur aut perferendis doloribus asperiores rep
ellat."        1914 translation by H.

LIPSUM

... mà in ...

Section 1.10.32 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.
Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.
Ut enim ad minima veniam, quis     ...
...
reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat."        1914 translation by H.

@don_crissti - ừ - lạ quá. Nó đã làm việc w / busybox xargs. Và nó không w / read, nhưng không khác. Phải mất rất ít để chắc chắn hơn trích dẫn nó - tôi đoán tôi phải làm. Hoặc nếu không đặt một tr -d \\ngiữa sedxargs. (Tôi chỉ làm nó trong vỏ trên máy tính bảng Android của tôi trong phòng tắm, một cách trung thực)
mikeserv
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.