Bash: Bẻ khóa đường mòn từ đầu ra


187

Khi tôi thực thi các lệnh trong Bash (hoặc cụ thể, wc -l < log.txt), đầu ra chứa một ngắt dòng sau nó. Làm sao để tôi bỏ nó đi?

Câu trả lời:


248

Nếu đầu ra dự kiến ​​của bạn là một dòng đơn , bạn chỉ cần xóa tất cả các ký tự dòng mới khỏi đầu ra. Sẽ không có gì lạ khi chuyển sang tiện ích 'tr' hoặc Perl nếu được ưu tiên:

wc -l < log.txt | tr -d '\n'

wc -l < log.txt | perl -pe 'chomp'

Bạn cũng có thể sử dụng thay thế lệnh để xóa dòng mới:

echo -n "$(wc -l < log.txt)"

printf "%s" "$(wc -l < log.txt)"

Xin lưu ý rằng tôi không đồng ý với quyết định của OP về việc chọn câu trả lời được chấp nhận. Tôi tin rằng người ta nên tránh sử dụng 'xargs' nếu có thể. Vâng, nó là một món đồ chơi thú vị. Không, bạn không cần nó ở đây.


Nếu đầu ra dự kiến ​​của bạn có thể chứa nhiều dòng , bạn có một quyết định khác:

Nếu bạn muốn xóa NHIỀU ký tự dòng mới khỏi cuối tệp, một lần nữa sử dụng thay thế cmd:

printf "%s" "$(< log.txt)"

Nếu bạn muốn xóa hoàn toàn ký tự dòng mới LAST khỏi tệp, hãy sử dụng Perl:

perl -pe 'chomp if eof' log.txt


Lưu ý rằng nếu bạn chắc chắn rằng bạn có một ký tự dòng mới mà bạn muốn xóa, bạn có thể sử dụng 'head' từ GNU coreutils để chọn mọi thứ trừ byte cuối cùng. Điều này sẽ khá nhanh chóng:

head -c -1 log.txt

Ngoài ra, để hoàn thiện, bạn có thể nhanh chóng kiểm tra vị trí các ký tự dòng mới (hoặc đặc biệt khác) trong tệp của mình bằng cách sử dụng cờ 'cat' và cờ 'show-all'. Ký tự ký hiệu đô la sẽ chỉ ra phần cuối của mỗi dòng:

cat -A log.txt

Điều này loại bỏ TẤT CẢ các dòng mới từ đầu ra, không chỉ dòng mới theo sau như tiêu đề yêu cầu.
Cody A. Ray

@ CodyA.Ray: Mặc dù vậy, bạn phải đồng ý rằng câu hỏi mô tả một lệnh cụ thể sẽ chỉ tạo ra một dòng đầu ra duy nhất. Tuy nhiên, tôi đã cập nhật câu trả lời của mình cho phù hợp với trường hợp tổng quát hơn. HTH.
Steve

3
Điều này sẽ tốt hơn nếu các tùy chọn ngắn được thay thế bằng các tùy chọn dài. Các tùy chọn dài dạy cũng như chức năng, ví dụ tr --delete '\n'.
Elijah Lynn

1
Tôi cũng đã làm| tr -d '\r'
AlikElzin-kilaka

Điều đáng chú ý là giải pháp thay thế cmd có thể dẫn đến một dòng quá dài nếu tệp quá lớn.
phk

88

Một chiều:

wc -l < log.txt | xargs echo -n

24
Tốt hơn:echo -n `wc -l log.txt`
Satya

9
Tại sao thực hiện lệnh trong backticks tốt hơn là sử dụng một đường ống?
Matthew Schinckel

2
Những thứ này sẽ không chỉ loại bỏ các dòng mới, mà còn ép bất kỳ khoảng trắng liên tiếp nào (chính xác hơn, như được định nghĩa bởi IFS) vào một khoảng trắng . Ví dụ : echo "a b" | xargs echo -n; echo -n $(echo "a b"). Điều này có thể hoặc không thể là một vấn đề cho trường hợp sử dụng.
musiphil

14
Tệ hơn, nếu đầu ra bắt đầu bằng -e, nó sẽ được hiểu là tùy chọn echo. Nó luôn an toàn hơn để sử dụng printf '%s'.
musiphil

1
xargslà rất chậm trên hệ thống của tôi (và tôi nghi ngờ nó cũng ở trên các hệ thống khác), vì vậy printf '%s' $(wc -l log.txt)có thể nhanh hơn, vì printfthường là một nội dung (Cũng bởi vì không có chuyển hướng thông tin). Không bao giờ sử dụng backticks, chúng đã bị phản đối trong các phiên bản POSIX mới hơn và có nhiều nhược điểm.
yyny

13

Ngoài ra còn có hỗ trợ trực tiếp để loại bỏ khoảng trắng trong thay thế biến Bash :

testvar=$(wc -l < log.txt)
trailing_space_removed=${testvar%%[[:space:]]}
leading_space_removed=${testvar##[[:space:]]}

1
Bạn cũng có thể sử dụngtrailing_linebreak_removed=${testvar%?}
PairedPrototype

Lưu ý rằng nếu bạn đang sử dụng thay thế lệnh thì bạn không cần phải làm gì để xóa các dòng mới. Bash đã thực hiện điều đó như là một phần của sự thay thế lệnh: gnu.org/software/bash/manual/html_node/ Kẻ
Michael Burr

10

Nếu bạn chỉ định đầu ra của nó cho một biến, bashsẽ tự động loại bỏ khoảng trắng:

linecount=`wc -l < log.txt`

10
Chính xác là Trailing bị tước bỏ, chính xác. Đó là sự thay thế lệnh loại bỏ chúng, không phải là phép gán biến.
chepner

2
Tôi đã thấy trong Cygwin bash khoảng trắng theo dõi không bị xóa khi sử dụng $ (cmd / c echo% VAR%). Trong trường hợp này, tôi đã phải sử dụng $ {var %% [[: space:]]}.
Andrey Taranov

1
Lưu ý: nó không phải là phép gán biến, mà là mở rộng biểu thức loại bỏ các dòng mới.
Ciro Santilli 郝海东 冠状 病 事件

10

printf đã cắt dòng mới cho bạn:

$ printf '%s' $(wc -l < log.txt)

Chi tiết:

  • printf sẽ in nội dung của bạn thay cho %sngười giữ vị trí chuỗi.
  • Nếu bạn không bảo nó in một dòng mới ( %s\n), nó sẽ không.

7
Nếu bạn đặt dấu ngoặc kép xung quanh lệnh như thế "$(command)", các dòng mới bên trong sẽ được giữ nguyên - và chỉ dòng mới theo sau sẽ bị xóa. Shell đang thực hiện tất cả các công việc ở đây - printfchỉ là một cách để hướng kết quả thay thế lệnh trở lại stdout.
tộc

2
Đây không phải là bản in đang tước dòng mới ở đây, đó là phần vỏ đang thực hiện với $( )cấu trúc. Đây là bằng chứng:printf "%s" "$(perl -e 'print "\n"')"
Flimm

Một lần nữa, đáng chú ý là dòng lệnh kết quả có thể trở nên quá dài.
phk

Đây là một giải pháp tiện lợi với đề xuất của @ nobar:$ printf '%s' "$(wc -l < log.txt)"
Ilias Karim

8

Nếu bạn muốn xóa chỉ dòng mới nhất , hãy chuyển qua:

sed -z '$ s/\n$//'

sedsẽ không thêm \0vào cuối luồng nếu bộ phân cách được đặt thành NULthông qua -z, trong khi đó để tạo tệp văn bản POSIX (được xác định là kết thúc bằng a \n), nó sẽ luôn xuất ra một bản cuối cùng \nmà không có -z.

Ví dụ:

$ { echo foo; echo bar; } | sed -z '$ s/\n$//'; echo tender
foo
bartender

Và để chứng minh không NULthêm:

$ { echo foo; echo bar; } | sed -z '$ s/\n$//' | xxd
00000000: 666f 6f0a 6261 72                        foo.bar

Để xóa nhiều dòng mới , hãy bỏ qua:

sed -Ez '$ s/\n+$//'

Tôi cho rằng đây là một phần mở rộng GNU, Mac sedkhông cung cấp -z.
Spidey

5

Nếu bạn muốn in đầu ra của bất cứ thứ gì trong Bash mà không có dòng cuối, bạn lặp lại nó bằng công -ntắc.

Nếu bạn đã có nó trong một biến rồi, hãy lặp lại nó với dòng mới được cắt xén:

    $ testvar=$(wc -l < log.txt)
    $ echo -n $testvar

Hoặc bạn có thể làm điều đó trong một dòng, thay vào đó:

    $ echo -n $(wc -l < log.txt)

2
Các biến là không cần thiết về mặt kỹ thuật. echo -n $(wc -l < log.txt)có tác dụng tương tự.
chepner
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.