Làm thế nào để nối nhiều dòng đầu ra thành một dòng?


158

Nếu tôi chạy lệnh cat file | grep pattern, tôi nhận được nhiều dòng đầu ra. Làm thế nào để bạn nối tất cả các dòng thành một dòng, thay thế hiệu quả từng dòng "\n"bằng "\" "(kết thúc bằng dấu "cách)?

cat file | grep pattern | xargs sed s/\n/ /g không làm việc cho tôi.


Nhân tiện: (1) bạn cần đặt sedtập lệnh của mình vào dấu ngoặc đơn để Bash không gây rối với nó (vì sed s/\n/ /gcác cuộc gọi sedcó hai đối số, cụ thể là s/n//g); (2) kể từ khi bạn muốn đầu ra của cat file | grep patternđầu vào để sed, chứ không phải tranh cãi để sed, bạn cần phải loại bỏ xargs; và (3) không cần catở đây, vì grepcó thể lấy tên tệp làm đối số thứ hai. Vì vậy, bạn nên đã cố gắng grep pattern file | sed 's/\n/ /g'. (Trong trường hợp này, nó sẽ không hoạt động, vì những lý do được đưa ra ở liên kết trên, nhưng bây giờ bạn biết cho tương lai.)
ruakh


Câu hỏi với 68 phiếu (140k lượt xem) trùng lặp với bài đăng chỉ có 1 phiếu (12k lượt xem)? Điều này không đúng.
kenorb

Câu trả lời:


231

Sử dụng tr '\n' ' 'để dịch tất cả các ký tự dòng mới sang dấu cách:

$ grep pattern file | tr '\n' ' '

Lưu ý: grepđọc tập tin, catnối tập tin. Đừngcat file | grep !

Biên tập:

trchỉ có thể xử lý các bản dịch ký tự đơn. Bạn có thể sử dụng awkđể thay đổi dấu tách bản ghi đầu ra như:

$ grep pattern file | awk '{print}' ORS='" '

Điều này sẽ biến đổi:

one
two 
three

đến:

one" two" three" 

3
Bạn kết thúc với một không gian không mong muốn ở cuối với phương pháp này.
sorin

1
Bạn cần thêm echo ""vào cuối để thêm dòng mới trước văn bản nhắc nhở.
nexayq

1
Điều này hoạt động tốt, tuy nhiên tôi không muốn dấu phân cách hiển thị ở mục cuối cùng. Ví dụ, theo bạn ", nó hiển thị như thế nào one" two" three", tuy nhiên tôi muốn nó hiển thị như thế nào one" two" three. Lưu ý ba cái cuối cùng không có dấu ngoặc đơn. Có ý kiến ​​gì không?
oink

2
@oink bạn có thể dẫn kết quả vào sed '$s/..$//'để xóa 2 ký tự cuối cùng trên dòng cuối cùng.
Chris Seymour

3
Nếu bạn muốn thay thế dòng mới bằng không có gì, bạn cần sử dụng --deletetùy chọn này vì mặc định sẽ có hai đối số. ví dụ tr --delete '\n'.
Elijah Lynn

69

Đầu ra đường ống xargssẽ nối từng dòng đầu ra thành một dòng có khoảng trắng:

grep pattern file | xargs

Hoặc bất kỳ lệnh nào, vd. ls | xargs. Giới hạn xargsđầu ra mặc định là ~ 4096 ký tự, nhưng có thể tăng lên với ví dụ. xargs -s 8192.


| tr '\n' ' 'đã không làm việc cho tôi khi được gọi thông qua php execchức năng. Nó đã bỏ qua tr, và chỉ đưa ra trận đấu cuối cùng từ grep. | xargsđã làm việc.
Adarsha

3
Giải pháp này cũng có lợi thế là nó 'ăn' không gian từ đầu vào. +1
Rene

55

Trong bash echokhông có dấu ngoặc kép, loại bỏ trả lại vận chuyển, tab và nhiều khoảng trắng

echo $(cat file)

8
Câu trả lời bị đánh giá thấp ở đây, điều này thực sự đơn giản và hoạt động như một cơ duyên, với một dòng mới.
Dangercrow

Điều này đặc biệt gọn gàng nếu bạn sử dụngIFS="$(printf '\n\t')"
agssol

5
Hoặc chỉ echo $(<file)... sử dụng echo không chỉ gọn gàng hơn sử dụng tr '\n' ' ', mà còn tốt hơn (nghĩ \r\nkết thúc dòng). @aggieol bạn chỉ có thể nóiIFS=$'\n\t'
Normadize

Làm thế nào về không có không gian?
DimiDak

22

Đây có thể là những gì bạn muốn

cat file | grep pattern | paste -sd' '

Theo chỉnh sửa của bạn, tôi không chắc nó có nghĩa gì, có lẽ đây?

cat file | grep pattern | paste -sd'~' | sed -e 's/~/" "/g'

(điều này giả định ~không xảy ra trong file)


2
@Stephan không cần phải giả định rằng cat filenó thực sự sẽ là cat, hoặc thậm chí là một tập tin. (Tôi chỉ để phần đó không thay đổi vì nó không liên quan đến câu hỏi)
sehe

5

Đây là một ví dụ tạo ra đầu ra riêng biệt bằng dấu phẩy. Bạn có thể thay thế dấu phẩy bằng bất kỳ dấu phân cách nào bạn cần.

cat <<EOD | xargs | sed 's/ /,/g'
> 1
> 2
> 3
> 4
> 5
> EOD

sản xuất:

1,2,3,4,5

3

Đây là phương pháp sử dụng extrình soạn thảo (một phần của Vim ):

  • J oin tất cả các dòng và p rint đến đầu ra tiêu chuẩn:

    $ ex +%j +%p -scq! file
  • J oin tất cả các dòng tại chỗ (trong tệp):

    $ ex +%j -scwq file

    Lưu ý: Điều này sẽ tự ghép tất cả các dòng bên trong tệp!


2

Cách nhanh nhất và dễ nhất tôi biết để giải quyết vấn đề này:

Khi chúng tôi muốn thay thế ký tự dòng mới \n bằng dấu cách :

xargs < file

xargscó giới hạn riêng về số lượng ký tự trên mỗi dòng và số lượng tất cả các ký tự được kết hợp, nhưng chúng ta có thể tăng chúng. Chi tiết có thể được tìm thấy bằng cách chạy lệnh này: xargs --show-limitsvà tất nhiên trong hướng dẫn:man xargs

Khi chúng ta muốn thay thế một ký tự bằng một ký tự khác chính xác :

tr '\n' ' ' < file

Khi chúng tôi muốn thay thế một ký tự bằng nhiều ký tự :

tr '\n' '~' < file | sed s/~/many_characters/g

Đầu tiên, chúng tôi thay thế các ký tự dòng mới \ncho ~dấu ngã (hoặc chọn một ký tự duy nhất khác không có trong văn bản), sau đó chúng tôi thay thế các ký tự dấu ngã bằng bất kỳ ký tự nào khác ( many_characters) và chúng tôi làm điều đó cho mỗi dấu ngã (cờ g).


0

Có lẽ cách tốt nhất để làm điều đó là sử dụng công cụ 'awk' sẽ tạo đầu ra thành một dòng

$ awk ' /pattern/ {print}' ORS=' ' /path/to/file

Nó sẽ hợp nhất tất cả các dòng thành một với dấu phân cách không gian


Bạn không cần {print}vì hành động mặc định của awk.
stark

0

Đây là một phương pháp đơn giản khác sử dụng awk:

# cat > file.txt
a
b
c

# cat file.txt | awk '{ printf("%s ", $0) }'
a b c

Ngoài ra, nếu tệp của bạn có các cột, điều này cung cấp một cách dễ dàng để chỉ ghép các cột nhất định:

# cat > cols.txt
a b c
d e f

# cat cols.txt | awk '{ printf("%s ", $2) }'
b e

-1

Trên linux mũ đỏ tôi chỉ sử dụng echo:

echo $ (cat / some / file / name)

Điều này cung cấp cho tôi tất cả các hồ sơ của một tập tin chỉ trên một dòng.


2
Điều này như đã được trả lời trong năm 2015. Bạn chỉ cần sao chép câu trả lời này . Vui lòng đọc câu trả lời trước khi đăng bài của riêng bạn, đặc biệt khi câu hỏi đã 7 tuổi và đã có 8 câu trả lời.
Mickael B.
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.