Làm cách nào để xóa ký tự dòng mới ở cuối tệp?


34

Hãy để tôi nói rõ về nhân vật dòng mới:

$ echo Hello > file1 ; cat file1
Hello
$ echo -n  Hello > file2 ; cat file2
Hello$ 

Ở đây bạn có thể thấy rằng file1có ký tự dòng mới ở cuối trong khi file2không.

Bây giờ giả sử tôi có một file:

$ cat file
Hello
Welcome to
Unix
$

Và tôi muốn thêm and Linuxvào cuối tập tin, sau đó echo " and Linux" >> filesẽ được thêm vào dòng mới. Nhưng tôi muốn dòng cuối cùng làUnix and Linux

Vì vậy, để làm việc xung quanh tôi muốn xóa ký tự dòng mới ở cuối tệp. Vì vậy, làm cách nào để xóa ký tự dòng mới ở cuối tệp?


6
Đừng xóa nó, chỉ cần sử dụng một trình soạn thảo văn bản. sed '$s/$/ and linux/'
123

Câu trả lời:


28

Nếu tất cả những gì bạn muốn làm là thêm văn bản vào dòng cuối cùng, thì rất dễ dàng với sed. Thay thế $(khớp mẫu ở cuối dòng) bằng văn bản bạn muốn thêm, chỉ trên các dòng trong phạm vi $(có nghĩa là dòng cuối cùng).

sed '$ s/$/ and Linux/' <file >file.new &&
mv file.new file

mà trên Linux có thể rút ngắn thành

sed -i '$ s/$/ and Linux/' file

Nếu bạn muốn loại bỏ byte cuối cùng trong một tệp, Linux (chính xác hơn là GNU coreutils) cung cấp truncatelệnh này, điều này làm cho việc này rất dễ dàng.

truncate -s -1 file

Một cách POSIX để làm điều đó là với dd. Đầu tiên xác định độ dài tệp, sau đó cắt ngắn nó xuống một byte.

length=$(wc -c <file)
dd if=/dev/null of=file obs="$((length-1))" seek=1

Lưu ý rằng cả hai điều này đều cắt ngắn vô điều kiện byte cuối cùng của tệp. Bạn có thể muốn kiểm tra xem đó là dòng mới trước:

length=$(wc -c <file)
if [ "$length" -ne 0 ] && [ -z "$(tail -c -1 <file)" ]; then
  # The file ends with a newline or null
  dd if=/dev/null of=file obs="$((length-1))" seek=1
fi

9
Cách tốt hơn nhiều để loại bỏ một dòng mớiperl -pi -e 'chomp if eof' myfile. So với truncatehoặc ddnó sẽ không để lại cho bạn một tập tin bị hỏng nếu myfilethực sự không có dòng mới.
Hi-Angel

2
@ Hi-Angel Tôi có thể khuyên bạn nên viết như một câu trả lời không? Tôi nghĩ rằng đó sẽ là một câu trả lời rất tốt.
Simon Forsberg

@SimonForsberg cảm ơn, đã xong .
Hi-Angel

17

Mặc dù vậy, bạn có thể xóa ký tự dòng mới khỏi dòng bằng cách tr -d '\n':

$ echo -e "Hello"
Hello
$ echo -e "Hello" | tr -d '\n'
Hello$

Bạn có thể xóa ký tự dòng mới ở cuối tệp bằng cách dễ dàng sau đây:

  1. head -c -1 file

    Từ man head:

    -c, --bytes=[-]K
              print the first K bytes of each file; with the leading '-',
              print all but the last K bytes of each file
  2. truncate -s -1 file

    từ man truncate:

    -s, --size=SIZE
              set or adjust the file size by SIZE

    SIZE is an integer and optional unit (example: 10M is 10*1024*1024).
    Units are K, M, G, T, P, E, Z, Y (powers of 1024) or KB, MB, ... (powers of 1000).
    
    SIZE  may  also be prefixed by one of the following modifying characters: 
    '+' extend by, '-' reduce by, '<' at most, '>' at least, '/' round down to multiple of, '%' round up to multiple of.

head -c -1 file | tee filean toàn không Sẽ không teecắt bớt tập tin trước khi bắt đầu?
iruvar

1
@ 1_CR Thật vậy. Hai bên của đường ống bắt đầu song song, đó là vấn đề ai thắng cuộc đua. Vì teechỉ phải mở tệp, trong khi headphải đọc và viết nội dung của nó, teetrên thực tế sẽ giành chiến thắng trong cuộc đua ngoại trừ đôi khi đối với các tệp rất nhỏ.
Gilles 'SO- ngừng trở nên xấu xa'

2
Điều này không loại bỏ dòng mới nhất, nó loại bỏ tất cả các dòng mới. IMO một sự khác biệt khá lớn.
Hi-Angel

9

Bạn có thể đạt được điều này với perl như:

perl -pi -e 'chomp if eof' myfile

So với truncatehoặc ddđiều này sẽ không để lại cho bạn một tập tin bị hỏng nếu myfilethực sự không có dòng mới.

(câu trả lời được xây dựng từ nhận xét và dựa trên câu trả lời này )


Cảm ơn bạn! Phương pháp loại bỏ có điều kiện này là theo dõi dòng mới là hoàn hảo.
xer0x

2

Đây là một cách với sed- trên dòng ( $) cuối cùng của tệp, tìm kiếm và thay thế mọi thứ và mọi thứ ( .*) bằng "bất cứ thứ gì bạn khớp" theo sau là "và Linux":

sed '$s/\(.*\)/\1 and Linux/' file

Một giải pháp thậm chí đơn giản hơn, lịch sự của Isaac , là:

sed '$s/$/ and Linux/' file

Điều này thay thế cuối dòng (tượng trưng) bằng văn bản đã cho.


Isaac, tôi thích đề nghị đó! Nó đơn giản / rõ ràng hơn. Tôi sẽ cập nhật câu trả lời với nó. Cảm ơn bạn!
Jeff Schaller
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.