2010-07-16 66 views
6

Đây là một khái niệm rất cơ bản, nhưng một cái gì đó tôi chưa bao giờ có thể nói rõ điều đó. và tôi muốn thử đánh vần nó và xem tôi đã đi sai ở đâu.Ký tự dòng mới là gì - ' n'

Nếu tôi phải làm thế nào, tôi sẽ xác định "ký tự dòng mới" như thế nào. nói rằng nếu tôi tạo một tệp mới trong unix (hoặc cửa sổ), thì tệp lưu trữ thông tin "cuối dòng" bằng cách chèn một ký tự đặc biệt vào tệp được gọi là "ký tự dòng mới". Nếu vậy, giá trị ascii của nó là gì? Tôi nhớ rằng trong các chương trình C, tôi đã kiểm tra ký tự đọc với giá trị '\ n'. Và tại sao điều này gây nhầm lẫn cho 2 nhân vật đại diện cuối của các nhân vật dòng ..

bash$ cat states 
California 
Massachusetts 
Arizona 

Say, tôi muốn chèn một không gian ranh giới giữa các dòng và muốn có một đầu ra có dạng: đầu ra mong muốn:

California 

Massachusetts 

Arizona 

bash$sed -e 's/\n/\n\n/g' states does not work. 

Tại sao tôi không thể xử lý "ký tự dòng mới" ở đây giống như tôi sẽ đối xử với bất kỳ ký tự nào khác và chạy một cái gì đó như lệnh trên. (Tôi hiểu rằng người ta có thể nói rằng đây là một vấn đề cú pháp của sed, nhưng có thể xin giải thích trực giác đằng sau không cho phép điều này, để tôi có thể thoát khỏi sự nhầm lẫn của tôi. tôi không thể sử dụng:.?% s/\ n/\ n \ n/g tại sao nên

tôi có cần phải thoát ra thêm \ n bằng cách sử dụng một dấu chéo ngược trong sed và từ bên trong vim ?.

Cảm ơn ,

Jagrati

+3

* Và tại sao điều này gây nhầm lẫn 2 ký tự đại diện cho các ký tự cuối dòng. * - Đối với chương trình, nó không thực sự là hai ký tự - đó là một ký tự "thoát" bằng dấu gạch chéo ngược. Trình biên dịch hiểu rằng nó đại diện cho một giá trị khác với một ASCII bình thường ** 'n' **. Thoát ký tự thường được sử dụng trong nhiều ngôn ngữ và nền tảng để thể hiện các ký tự mà bạn có thể không đại diện. – GalacticCowboy

+2

Làm quen với những gì Galactic Cowboy đã nói, '\ n' không phải là ký tự dòng mới, nó là biểu tượng * đại diện * ký tự dòng mới trong ký tự C và chuỗi ký tự (và trong một số ngữ cảnh khác). Tất nhiên, ký tự dòng mới thực sự trong mã nguồn sẽ ẩn, ngoại trừ việc nó sẽ kết thúc dòng. Đây là lý do tại sao bạn gặp vấn đề với sed: '\ n' không đại diện cho ký tự dòng mới trong chương trình đó. –

+2

Tôi thề tôi đã đọc "Nhân vật mới là gì - '\ n'", vì vậy mệt mỏi – Enriquev

Trả lời

10

Từ sed man page:

Thông thường, sed chu kỳ bản sao một dòng đầu vào, không bao gồm chấm dứt của nó kí tự xuống dòng, vào một không gian mô hình, (trừ khi có cái gì đó còn lại sau khi một "D" chức năng), áp dụng tất cả các lệnh với các địa chỉ chọn không gian mẫu đó, sao chép không gian mẫu vào đầu ra tiêu chuẩn, nối thêm một dòng mới và xóa không gian mẫu.

Nó hoạt động trên dòng mà không có dòng mới, vì vậy mẫu bạn có ở đó không bao giờ có thể khớp. Bạn cần phải làm điều gì đó khác - như kết hợp với $ (cuối dòng) hoặc ^ (bắt đầu-of-line).

Dưới đây là một ví dụ về một cái gì đó mà làm việc cho tôi:

$ cat > states 
California 
Massachusetts 
Arizona 
$ sed -e 's/$/\ 
> /' states 
California 

Massachusetts 

Arizona 

Tôi gõ một ký tự xuống dòng đen sau khi \ trong dòng sed.

+0

'\ n' * làm * hoạt động trong' sed', vì vậy bạn cũng có thể chỉ sử dụng 'sed' s/$/\ n/'states' – jabirali

+1

+1 để đề cập đến không gian mẫu btw :-) – jabirali

+0

@Jabir , không phải trên máy của tôi. –

11

Dòng mới (\ n) là 10 (0xA) và CarriageReturn (\ r) là 13 (0xD).

Hệ điều hành khác nhau đã chọn các biểu diễn cuối dòng khác nhau cho tệp. Windows sử dụng CRLF (\ r \ n). Unix sử dụng LF (\ n). Các phiên bản Mac OS cũ hơn sử dụng CR (\ r), nhưng OS X đã chuyển sang ký tự Unix.

Đây là một tương đối hữu ích FAQ.

+10

OS 9 sử dụng '\ r'; họ bỏ nó trong OS X và chuyển sang khớp với Unix –

+4

+1 @Michael, OS X chắc chắn không sử dụng '\ r'. –

+0

Phải, đã sửa. Bạn biết đấy, bạn cũng có thể chỉnh sửa câu trả lời. :) –

3
sed 's/$/\n/' states 
+0

Trong tệp được mã hóa với bộ ký tự us-ascii, nó không hợp lệ. Bạn phải lấy mã ASCII. – ssoto

0

Hãy thử điều này:

$ sed -e $'s/\n/\n\n/g' states 
5

ký tự thoát phụ thuộc vào bất cứ điều gì hệ thống được giải thích chúng. \n được hiểu là một ký tự dòng mới bởi nhiều ngôn ngữ lập trình, nhưng điều đó không nhất thiết phải đúng với các tiện ích khác mà bạn đề cập đến. Ngay cả khi họ xử lý \n làm dòng mới, có thể có một số kỹ thuật khác để khiến họ hành xử theo cách bạn muốn. Bạn sẽ phải tham khảo tài liệu của họ (hoặc xem các câu trả lời khác ở đây).

Đối với hệ điều hành DOS/Windows, dòng mới thực sự là hai ký tự: Trả về vận chuyển (ASCII 13, AKA \r), tiếp theo là Nguồn cấp dữ liệu dòng (ASCII 10). Trên các hệ thống Unix (bao gồm cả Mac OSX), nó chỉ là Line Feed. Trên các máy Mac cũ, nó là một chiếc Carriage Return.

1

Tôi nghĩ rằng this bài đăng của Jeff Attwood giải quyết câu hỏi của bạn một cách hoàn hảo. Nó sẽ đưa bạn qua sự khác biệt giữa các dòng mới trên Dos, Mac và Unix, và sau đó giải thích lịch sử của CR (Vận chuyển trở lại) và LF (Nguồn cấp dữ liệu dòng).

+0

Bài đăng đó có nội dung cơ bản của vấn đề, nhưng nó cũng có một số lỗi thực tế và một nửa sự thật. Bạn có thể nên đọc chủ đề mới của Wikipedia. –

1

sed có thể được đưa vào tìm kiếm nhiều dòng & thay thế chế độ để khớp với các ký tự dòng mới \n.

Để làm như vậy sed trước tiên phải đọc toàn bộ tệp hoặc chuỗi vào bộ đệm giữ ("giữ khoảng trống") để sau đó có thể xử lý nội dung tệp hoặc chuỗi dưới dạng một dòng trong "không gian mẫu".

Để thay thế một dòng mới một cách hợp lý (đối với GNU và FreeBSD sed), bạn có thể sử dụng dòng mới "thực" đã thoát.

# cf. http://austinmatzko.com/2008/04/26/sed-multi-line-search-and-replace/ 
echo 'California 
Massachusetts 
Arizona' | 
sed -n -e ' 
# if the first line copy the pattern to the hold buffer 
1h 
# if not the first line then append the pattern to the hold buffer 
1!H 
# if the last line then ... 
$ { 
# copy from the hold to the pattern buffer 
g 
# double newlines 
s/\n/\ 
\ 
/g 
s/$/\ 
/
p 
}' 

# output 
# California 
# 
# Massachusetts 
# 
# Arizona 
# 

Có, tuy nhiên, một thuận tiện hơn nhiều là để đạt được kết quả tương tự:

echo 'California 
Massachusetts 
Arizona' | 
    sed G 
0

Tôi nhìn thấy rất nhiều câu trả lời sed, nhưng không ai cho vim. Để công bằng, việc xử lý các ký tự dòng mới của vim là một chút khó hiểu. Tìm kiếm \ n nhưng thay thế bằng \ r. Tôi khuyên bạn nên sử dụng RTFM: :help pattern nói chung và :help NL-used-for-Nul nói riêng.

Để làm những gì bạn muốn với một: lệnh thay thế,

:%s/\_$/\r 

mặc dù tôi nghĩ hầu hết mọi người sẽ sử dụng một cái gì đó giống như

:g/^/put='' 

cho tác dụng tương tự.

Đây là cách để tìm câu trả lời cho chính bạn. Chạy tệp của bạn thông qua xxd, là một phần của phân phối vim chuẩn.

:%!xxd 

Bạn nhận được

0000000: 4361 6c69 666f 726e 6961 0a4d 6173 7361 California.Massa 
0000010: 6368 7573 6574 7473 0a41 7269 7a6f 6e61 chusetts.Arizona 
0000020: 0a          . 

Điều này cho thấy 46 là mã hex cho C, 61 là mã cho một, và vân vân.Cụ thể, 0a (số thập phân 10) là mã cho \ n. Chỉ để đá, hãy thử

:set ff=dos 

trước khi lọc qua xxd. Bạn sẽ thấy 0d0a (CRLF) làm trình kết thúc dòng.

:help /\_$ 
:help :g 
:help :put 
:help :! 
:help 23.4 
Các vấn đề liên quan