bash - ganti ruang dengan baris baru


70

Bagaimana saya bisa mengganti spasi dengan baris baru pada input seperti:

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

Untuk mendapatkan yang berikut ini:

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

Catatan

Saya memposting pertanyaan ini untuk membantu pengguna lain, tidak mudah untuk menemukan jawaban yang berguna di UNIX SE sampai saya mulai mengetik pertanyaan ini. Setelah itu saya menemukan yang berikut:

Pertanyaan terkait

Bagaimana saya bisa menemukan dan mengganti dengan baris baru?



ls / path / ke / | xargs echo | sed 's / \ s \ + / \ n / g'
SD.

Jawaban:



20

Dalam hal ini saya akan menggunakan printf:

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

Jika ada spasi di dalam salah satu jalur, Anda dapat mengutip filepath untuk mencegahnya terpecah pada spasi:

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

Untuk mengubah teks secara umum, tradalah taruhan terbaik Anda, seperti tercakup dalam jawaban yang ada.


1
Catatan singkat dari masa depan: terima kasih telah memposting solusi ini, sudah sangat andal bagi saya, dibandingkan dengan menggunakan "echo".
Liesmith

5

Dengan asumsi Anda memiliki string dengan spasi sebagai pemisah:

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

Namun Anda mungkin mengajukan pertanyaan yang salah. (Tidak harus, misalnya ini mungkin muncul dalam makefile.) Daftar nama file yang dipisahkan spasi tidak benar-benar berfungsi: bagaimana jika salah satu nama file berisi spasi?

Jika suatu program menerima nama file sebagai argumen, jangan bergabung dengan spasi. Gunakan "$@"untuk mengaksesnya satu per satu. Meskipun echo "$@"mencetak argumen dengan spasi di antaranya, itu karena echo: ia mencetak argumennya dengan spasi sebagai pemisah. somecommand "$@"meneruskan nama file sebagai argumen terpisah ke perintah. Jika Anda ingin mencetak argumen pada baris yang berbeda, Anda dapat menggunakan

printf '%s\n' "$@"

Jika Anda memiliki nama file yang dipisahkan oleh ruang dan Anda ingin meletakkannya dalam array untuk mengatasinya, Anda dapat menggunakan ekspansi variabel yang tidak dikutip untuk membagi nilai pada karakter IFS(Anda harus menonaktifkan ekspansi wildcard dengan set -f, jika tidak, pola akan diperluas nilainya):

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 

Anda bisa merangkum ini dalam fungsi yang mengembalikan -fpengaturan dan nilai IFSketika selesai:

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 

Mengubah jawaban yang benar untuk yang ini. Saya pikir lebih tepat untuk meneliti bagaimana saya sampai pada daftar yang dipisahkan oleh ruang, dan mengambil informasi itu dengan cara lain. Akan keren untuk pelajar seperti saya jika Anda berkomentar sedikit snipnet Anda, memberi tahu kami apa hal-hal seperti var IFS lokal atau kondisi $ - = f lakukan. Hal-hal semacam itu yang seseorang yang menggunakan bash beberapa kali tidak tahu.
laconbass

@ laconbass Saya telah menambahkan penjelasan singkat. Cari set -fdan IFSdi manual bash jika Anda ingin semua detailnya. Lihat juga unix.stackexchange.com/questions/16192/...
Gilles 'SO- stop being evil'

@Guilles Penjelasan singkat itu sudah cukup bagi saya, dan saya pikir itu akan menjadi untuk banyak orang lain. Ty untuk waktu Anda
laconbass

pengaturan IFSlokal tidak berlaku
Eliran Malka

@ EliranMalka Saya tidak tahu apa yang Anda maksudkan dengan ini. Jika skrip tidak berlaku seperti yang Anda pikirkan, Anda dapat mengajukan pertanyaan di sini.
Gilles 'SO- berhenti menjadi jahat'

4

Bersikap pragmatis, gunakan sed !!

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

Kata di atas mengatakan untuk mengganti satu atau lebih karakter spasi putih (\ s +) dengan baris baru (\ n)

Ini kurang lebih:

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

1
ganti perubahan dengan pengganti, itulah arti sebenarnya dari singkatan!
Rob

@Rob terima kasih, ingat Anda dapat mengedit jawaban orang lain.
MGP

1
Jika Anda memiliki beberapa spasi di antara teks maka Anda akan mendapatkan baris kosong. Anda perlu menambahkan '+' setelah \ untuk menunjukkan bahwa Anda ingin mencocokkan setidaknya satu spasi seperti yang seharusnya tepat satu ruang. yaitu. sed 's / \ s + / \ n / g'
DarkHeart

4

Sebagai alternatif trdari @laconbass, Anda juga dapat menggunakan xargsdalam hal ini:

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

Keuntungannya adalah ia bekerja bahkan dengan banyak spasi putih, yang trtidak.


0

Inilah cara saya melakukannya:

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

Perhatikan penggunaan tombol Enter setelah backslash dalam sedperintah.


prons dan kontra apa yang telah sedberakhir tr?
laconbass

Tingkat kenyamanan Anda :-) Saya pikir Anda dapat melakukan lebih banyak sedkarena merupakan editor daripada hanya menerjemahkan karakter.
unxnut

4
seddapat melakukan lebih banyak lagi, tetapi benar-benar berlebihan untuk ini. tradalah alat yang tepat untuk pekerjaan INI, tetapi pengetahuan seddan regex tentu akan berguna nanti!
Rob

0

Pendekatan lain, dengan asumsi baris dalam variabel yang disebut line:

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

Ini memanfaatkan fakta bahwa Bash membagi argumennya pada spasi putih secara default dan echomenambahkan baris baru ke inputnya secara default.


Saya mencoba ini di sistem ubuntu saya sebelum saya memposting pertanyaan ini dan tidak bisa berfungsi.
laconbass

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

adalah metode lain untuk mengubah kata-kata yang dipisahkan satu spasi menjadi baris yang dipisahkan.


-1

Skrip berikut mudah dimengerti dan mudah digunakan.

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

2
Inti dari jawaban Anda ( tr) sama dengan jawaban yang diterima. Selain itu jawaban Anda memiliki masalah berikut: a) perintah tidak diindentasi dengan 4 spasi (-> tata letak markdown) b) Penggunaan Anda cattidak berguna (Anda dapat menggantinya dengan < filename tr ' ' '\n'). c) Nama file keluaran Anda sama dengan nama file input. Dengan itu Anda membuat perlombaan data.
maxschlepzig

1
selain dari analisis maxschlepzig yang benar, ini bukan skrip, tetapi sekelompok perintah yang terhubung yang memiliki nama yang di-hardcod (karena skrip diharapkan memiliki header yang menentukan shell untuk digunakan dan menggunakan dua parameter untuk menentukan dalam dan output). Selain itu, 2 dari 3 orang di rumah saya tidak mudah memahaminya. Mungkin itu tidak representatif, tetapi perlu diingat bahwa sesuatu yang Anda sendiri pahami (atau dalam hal ini pikir Anda pahami) selalu tampak mudah.
Anthon
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.