Bash - Urutan angka di baris yang sama


20

Saya tahu perintah sequntuk menghasilkan urutan bilangan bulat, satu per baris, tetapi saya ingin mengajukan dua pertanyaan:

  1. Apakah mungkin untuk menulis nomor urut dalam baris yang sama?

  2. Apakah mungkin untuk membuat string yang dibuat dari urutan angka yang dipisahkan oleh spasi putih?


Shell memperlakukan baris baru seperti spasi sebagai pemisah argumen. Jadi, sementara seq memiliki argumen pemisah, dan bahkan lebih sederhana untuk mengatakannya adalah hanyaecho $(seq 1 10)
user3188445

1
@ user3188445, ini operator split + glob yang melakukan hal itu (yang menggunakan variabel khusus IFS yang secara default memang mengandung ruang dan baris baru tetapi dapat diubah), terpisah dari kata tokenization yang dilakukan oleh shell.
Stéphane Chazelas

Jawaban:



21

GNU seqmengambil -sopsi separator ( ):

$ seq -s ' ' 1 5
1 2 3 4 5

$ var="$(seq -s ' ' 1 5)"
$ echo "$var"
1 2 3 4 5

1
echo $(seq 5)bekerja dengan baik.

13

Portabel untuk semua shell dan sistem apa pun yang memiliki seq (karena pertanyaan ini ditandai)

Jika mulai adalah 1:

$ echo $(seq 10)
1 2 3 4 5 6 7 8 9 10

Jika tidak:

$ echo $(seq 5 10)
5 6 7 8 9 10

Dengan bc:

$ echo $(echo "for (i=0;i<=1000;i++) i"| bc)

Di bash

echo {1..10}

catatan:

Solusi gema ini berfungsi jika nilai IFS berisi baris baru, yang dilakukan secara default.
Secara default IFS diatur ke urutan <spasi> <tab> <newline> . Dan diatur ulang untuk setiap awal bersih shell. Tetapi, jika Anda memiliki kekhawatiran bahwa itu mungkin telah berubah dalam beberapa kasus sudut ekstrim, kami memiliki beberapa solusi.

Di bawah bash, zsh, ksh gunakan saja: IFS = $ '\ t \ n' (lewati semua jawaban ini).


Namun, mengatur ulang nilai IFS di bawah sh mungkin rumit. Baca detail lengkap di sini .

Batalkan IFS.

$ unset IFS; echo $(seq 5 10)                           #Always work.

akan selalu bekerja. Asalkan tidak akan ada kode di bawah ini (atau skrip anak) yang perlu ditetapkan IFS, seperti skrip yang melakukannya OldIFS="$IFS".

Solusi yang benar.

Menggunakan trik untuk sh:

sh -c 'IFS="$(printf " \t\nx")"; IFS="${IFS%x}"; printf "$IFS"|xxd'  # correct.

Komentar bukan untuk diskusi panjang; percakapan ini telah dipindahkan ke obrolan .
terdon

1
Sebagian besar implementasi sh akan mengabaikan IFS yang ditemukan di lingkungan (pengecualian adalah beberapa turunan abu, versi yang sangat lama dari beberapa shell Bourne dan versi terbaru dari posh). Catatan bahwa Anda hanya bisa melakukan IFS='<space><tab><newline>' di mana orang-orang <space>, <tab>, <newline>adalah karakter literal yang sesuai.
Stéphane Chazelas


0
seq 10 |xargs

...atau...

seq 10 |paste -s -

Kedua perintah di atas akan memisahkan bilangan bulat berdasarkan spasi. xargsdefault untuk meniru /bin/echodan setiap integer dipisahkan oleh satu ruang. Ini akan default ke panjang baris perintah maks 128K, meskipun. Anda dapat menyesuaikan ini ...

seq 100000 | xargs -s2093009 | wc -l

... mencetak 1. Saya nilai untuk di -ssini tidak sembarangan - Saya mendapatkannya setelah mencoba nilai yang lebih tinggi (yang ternyata tetap berhasil) tetapi kemudian xargsmencetak pesan yang membantu:

-s value should be <2093010

pasteadalah salah satu dari dua (sepengetahuan saya) utilitas yang disetujui POSIX untuk menangani jalur dengan panjang sewenang-wenang:

pastespesifikasi penggunaan aplikasi :

Sebagian besar utilitas standar berfungsi pada file teks . The cututilitas dapat digunakan untuk mengubah file dengan panjang garis sewenang-wenang dalam satu set file teks yang berisi data yang sama. The pasteutilitas dapat digunakan untuk membuat (atau buat ulang) file dengan panjang garis sewenang-wenang.

file teks

File yang berisi karakter yang disusun dalam nol atau lebih baris. Garis tidak mengandung karakter NUL dan {LINE_MAX}panjangnya tidak boleh melebihi byte, termasuk \nkarakter ewline. Meskipun POSIX.1-2008 tidak membedakan antara file teks dan file biner (lihat standar ISO C) , banyak utilitas hanya menghasilkan output yang dapat diprediksi atau bermakna ketika beroperasi pada file teks. Utilitas standar yang memiliki batasan seperti itu selalu menentukan file teks di bagian STDIN atau INPUT FILES mereka .

pastedefault ke pembatas tab, dan karenanya akan ada tab di antara setiap integer mengikuti perintah kedua. Kamu bisa...

seq 10 |paste -sd ' ' - 

... gunakan -dsaklar elimiter untuk mengubah perilaku itu,


seq 10 | xargsberfungsi dengan baik, tetapi karena batas baris perintah, seq 100000 | xargsmenghasilkan 5 \nbaris yang dibatasi (pada sistem saya)
Peter.O

@ Peter.O - paste and cut` adalah dua utilitas sanksi POSIX untuk bekerja dengan garis panjang arbitrart. Yang mengatakan, xargs | xargsadalah suatu pilihan. Atau yang lainseq 100000|tr \\n \
mikeserv

Komentar bukan untuk diskusi panjang; percakapan ini telah dipindahkan ke obrolan .
terdon

@ Binzebra - tidak itu tidak - tidak seperti yang Anda pikirkan. Mengapa tidak mencoba mengatur $IFSke nomor? Dan bashlambat dalam wujudnya. Dalam jawaban Anda, Anda berbicara tentang sh- Anda bahkan tidak perlu mengatur $IFSdalam konteks itu - itu akan diteruskan melalui lingkungan jika diatur di sana. Dan itu tidak lebih pendek dari seq 100000|paste -syang mengalahkannya 5: 1. Dan pastetidak datang tanpa gotcha.
mikeserv

@ Binzebra - ayolah, mengapa saya berbohong? Apakah saya memiliki profil jawaban yang cukup besar di situs ini karena saya menikmati penyebaran informasi yang salah? Atau mungkin itu karena saya suka membantu orang dan menikmati tantangan belajar sementara saya melakukannya? Menurut Anda mana yang lebih masuk akal? Saya suka $IFS- saya menggunakannya sepanjang waktu - tapi saya tidak menggunakannya kecuali saya mengaturnya dan Anda juga tidak. Terutama Anda tidak harus merekomendasikan kepada orang asing acak yang tidak tahu lebih baik daripada harus melakukannya. Jangan biarkan kebetulan - ini adalah program komputer. Ini adalah bug jika berperilaku tidak terduga - mengapa membiarkannya terjadi?
mikeserv
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.