bash - thay thế không gian bằng dòng mới


70

Làm cách nào tôi có thể thay thế khoảng trắng bằng các dòng mới trên đầu vào như:

/path/to/file /path/to/file2 /path/to/file3 /path/to/file4 /path/to/file5 Vân vân...

Để có được những điều sau đây:

/path/to/file
/path/to/file2
/path/to/file3
/path/to/file4
/path/to/file5

Ghi chú

Tôi đang đăng câu hỏi này để giúp những người dùng khác, thật không dễ để tìm được câu trả lời hữu ích trên UNIX SE cho đến khi tôi bắt đầu gõ câu hỏi này. Sau đó tôi tìm thấy như sau:

Câu hỏi liên quan

Làm thế nào tôi có thể tìm và thay thế bằng một dòng mới?



ls / đường dẫn / đến / | tiếng vang xargs | sed 's / \ s \ + / \ n / g'
SD.

Câu trả lời:


125

Sử dụng trlệnh

echo "/path/to/file /path/to/file2 /path/to/file3 /path/to/file4 /path/to/file5"\
| tr " " "\n"

Tìm thấy trên http://www.unix.com/shell-programming-scripting/67831-replace-space-new-line.html


1
Tr cũng là suy nghĩ đầu tiên của tôi, mặc dù có rất nhiều cách để làm điều đó! Điều này là khá nhiều chính xác những gì trlà cho, mặc dù!
Cướp

5
+1, nhưng như một nhận xét: Điều đó không hoạt động nếu tên tệp chứa khoảng trắng
Bonsi Scott 17/12/13

20

Trong trường hợp này tôi sẽ sử dụng printf:

printf '%s\n' /path/to/file /path/to/file2 /path/to/file3 /path/to/file4 /path/to/file5

Nếu có khoảng trắng trong một trong các đường dẫn, bạn có thể trích dẫn filepath đó để ngăn không cho nó bị chia tách trên các khoảng trắng:

printf '%s\n' /path/to/file '/path/to/file with spaces' /path/to/another/file

Để chuyển đổi văn bản nói chung, trlà đặt cược tốt nhất của bạn, như được đề cập trong một câu trả lời hiện có.


1
Một lưu ý nhanh từ tương lai: cảm ơn bạn đã đăng giải pháp này, nó rất đáng tin cậy đối với tôi, so với việc sử dụng "echo".
Liesmith

5

Giả sử bạn có một chuỗi có dấu cách là dấu phân cách:

newline_separated=${space_separated// /$'\n'}

Tuy nhiên, có lẽ bạn đang hỏi sai câu hỏi. (Không nhất thiết, ví dụ, điều này có thể xuất hiện trong tệp tạo tệp.) Danh sách tên tệp được phân tách bằng dấu cách không thực sự hoạt động: nếu một trong các tên tệp chứa khoảng trắng thì sao?

Nếu một chương trình nhận tên tệp làm đối số, đừng tham gia chúng với khoảng trắng. Sử dụng "$@"để truy cập từng cái một. Mặc dù echo "$@"in các đối số có khoảng trắng ở giữa, nhưng đó là do echo: nó in các đối số của nó với khoảng trắng dưới dạng dấu phân cách. somecommand "$@"chuyển tên tệp dưới dạng đối số riêng biệt cho lệnh. Nếu bạn muốn in các đối số trên các dòng riêng biệt, bạn có thể sử dụng

printf '%s\n' "$@"

Nếu bạn không có không gian tách tên file và bạn muốn đặt chúng trong một mảng để làm việc với chúng, bạn có thể sử dụng một mở rộng biến không thể viện chứng để phân chia các giá trị tại các ký tự trên IFS(bạn sẽ cần phải vô hiệu hóa việc mở rộng ký tự đại diện với set -f, nếu không glob các mẫu sẽ được mở rộng trong giá trị):

space_separated_list='/path/to/file1 /path/to/file2 /path/to/file3'
IFS=' '; set -f
eval "array=(\$space_separated_list)"
for x in "${array[@]}"; do 

Bạn có thể gói gọn điều này trong một chức năng khôi phục -fcài đặt và giá trị IFSkhi hoàn thành:

split_list () {
  local IFS=' ' flags='+f'
  if [[ $- = *f* ]]; then flags=; fi
  set -f
  eval "$1=($2)"
  set $flags
}
split_list array '/path/to/file1 /path/to/file2 /path/to/file3'
for x in "${array[@]}"; do 

Thay đổi câu trả lời đúng cho câu hỏi này. Tôi nghĩ sẽ đúng hơn khi nghiên cứu cách tôi vào danh sách được phân tách bằng dấu cách và truy xuất thông tin đó theo cách khác. Sẽ thật tuyệt vời cho những người học như tôi nếu bạn bình luận một chút về snipnet của bạn, cho chúng tôi biết những việc cần làm như var IFS cục bộ hoặc điều kiện $ - = f làm. Đó là những điều mà một người sử dụng bash vài lần không biết.
laconbass

@laconbass Tôi đã thêm một lời giải thích ngắn. Tra cứu set -fIFStrong hướng dẫn bash nếu bạn muốn tất cả các chi tiết. Xem thêm unix.stackexchange.com/questions/16192/ trên
Gilles

@Guilles Lời giải thích ngắn đó là đủ cho tôi, và tôi nghĩ nó sẽ dành cho nhiều người khác. Ty cho thời gian của bạn
laconbass

thiết lập IFScục bộ không có hiệu lực
Eliran Malka

@EliranMalka Tôi không biết ý của bạn là gì. Nếu một kịch bản không hành xử theo cách bạn nghĩ, bạn có thể đặt câu hỏi tại đây.
Gilles

4

Hãy thực dụng, sử dụng sed !!

sed 's/\s\+/\n/g' file

Ở trên nói thay thế một hoặc nhiều ký tự khoảng trắng (\ s +) bằng dòng mới (\ n)

Đây là nhiều hay ít:

'substitute /one space or more/ for /newline/ globally'

1
thay thế thay thế bằng thay thế, đó là những gì thực sự đại diện cho!
Cướp

@Rob cảm ơn, hãy nhớ bạn có thể chỉnh sửa câu trả lời của người khác.
MGP

1
Nếu bạn có nhiều khoảng trắng giữa văn bản thì bạn sẽ nhận được các dòng trống. Bạn cần thêm '+' sau \ s để cho biết rằng bạn muốn khớp ít nhất một khoảng trắng như được gắn với chính xác một khoảng trắng. I E. sed 's / \ s + / \ n / g'
DarkHeart

4

Thay thế cho trtừ @laconbass, bạn cũng có thể sử dụng xargstrong trường hợp này:

echo "/path/to/file /path/to/file2 /path/to/file3 /path/to/file4  /path/to/file5"\
| xargs -n1

Ưu điểm là nó hoạt động ngay cả với nhiều khoảng trắng, điều trnày không có.


0

Đây là cách tôi đã làm nó:

echo "/path/to/file /path/to/file2 /path/to/file3 /path/to/file4 /path/to/file5" | sed 's/ /\
'/g

Lưu ý việc sử dụng phím Enter sau dấu gạch chéo ngược trong sedlệnh.


những gì prons và nhược điểm đã sedqua tr?
laconbass 17/12/13

Mức độ thoải mái của bạn :-) Tôi nghĩ bạn có thể làm được nhiều hơn sedvì đây là trình chỉnh sửa thay vì chỉ đơn giản là dịch các ký tự.
unxnut 17/12/13

4
sedcó thể làm nhiều hơn thế, nhưng hoàn toàn quá mức cho việc này. trlà công cụ phù hợp cho công việc NÀY, nhưng kiến ​​thức sedvà regexes chắc chắn sẽ có ích sau này!
Cướp

0

Một cách tiếp cận khác, giả sử dòng này nằm trong một biến gọi là line:

for path in $line;do echo $path;done

Điều này sử dụng thực tế là Bash chia tách các đối số của nó trên khoảng trắng theo mặc định và nó echonối thêm một dòng mới vào đầu vào của nó theo mặc định.


Tôi đã thử điều này trên hệ thống Ubuntu của tôi trước khi tôi đăng câu hỏi này và không thể làm cho nó hoạt động được.
laconbass 17/12/13

0
echo word1 word2 ... | sed -e 'y/ /\n/;P;D'

là một phương pháp khác để biến các từ được phân tách bằng dấu cách đơn thành dòng mới được phân tách.


-1

Kịch bản sau đây dễ hiểu và dễ sử dụng.

cat filename | tr ' ' '\n' | tee filename

2
Bản chất của câu trả lời của bạn ( tr) giống như trong câu trả lời được chấp nhận. Bên cạnh đó, câu trả lời của bạn có các vấn đề sau: a) lệnh không được thụt vào với 4 khoảng trắng (-> bố cục đánh dấu) b) Việc sử dụng của bạn catlà vô ích (bạn có thể thay thế bằng < filename tr ' ' '\n'). c) Tên tệp đầu ra của bạn giống với tên tệp đầu vào. Với điều đó bạn tạo ra một cuộc đua dữ liệu.
maxschlepzig

1
ngoài phân tích chính xác của maxschlepzig, đây không phải là một tập lệnh, mà là một loạt các lệnh được kết nối có tên mã hóa (vì tập lệnh hy vọng sẽ có một tiêu đề chỉ định shell để sử dụng và sử dụng hai tham số để chỉ định vào và ra). Ngoài ra, 2 trong số 3 người trong gia đình tôi không thấy dễ hiểu. Có thể đó không phải là đại diện, nhưng hãy nhớ rằng một cái gì đó bạn tự hiểu (hoặc trong trường hợp này nghĩ rằng bạn hiểu) luôn có vẻ dễ dàng.
Anthon
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.