Yang penting, :>bukan operator tunggal. Mungkin lebih mudah untuk dipahami jika Anda membacanya sebagai : > filegantinya.
jpfx1342
Ini berarti bahwa orang yang menulis script harus diarahkan output dari loop ke file: while read A B C D E; do echo "$A;$B;$D;$E;$C"; done < otherfile > file. Atau lebih baik lagi, mereka seharusnya menggunakan alat yang tepat untuk pekerjaan itu, awk, seperti yang disarankan oleh Peter . Selain itu, Anda hampir selalu ingin menggunakan -rsakelarread .
Tom Fenech
Di luar bash, itu akan menjadi senyuman bagi seekor gagak.
smci
Jawaban:
46
Ada:> dalam baris skrip bash. Apa artinya?
:> file
Ini adalah cara pintas untuk mengatakan:
Jika filetidak ada maka buat yang lain memotongnya menjadi 0byte.
Ini berarti Anda dapat yakin bahwa itu fileada dan kosong.
Anda juga dapat menggunakan > filetetapi :> filelebih portabel.
Saya tidak mengerti baris kedua. Saya pikir, itu membaca variabel baca. Perintah gema juga aneh. Bisakah Anda jelaskan?
diego9403
Saya bukan ahli Unix tapi saya pikir baris kedua membaca hal-hal dari otherfiledan ke echomereka file. Itu juga membuat variabel dari apa pun yang dibacanya ... Jika Anda ingin jawaban yang pasti silakan ajukan pertanyaan Anda sendiri.
DavidPostill
2
@ diego9403: readmendapat masukan dari stdin. Dengan sendirinya, itu akan membaca apa yang Anda ketik. Karena stdin telah dialihkan ke <otherfilemaka isi otherfile"diketik" ke dalam stdin. Jadi readdapatkan nilai-nilai baris demi baris ke dalam variabel $ A, $ B, $ C, $ D dan $ E.
slebetman
Jadi itu hanya alternatif yang lebih tidak jelas truncatedari dari coreutils?
Federico Poloni
1
@PeterCordes saya tidak bermaksud "tidak jelas" seperti pada "tidak biasa", tetapi seperti "kurang jelas bagi pembaca".
Federico Poloni
29
Sepertinya cara mewah untuk membuat file baru. In bash:adalah perintah nol:
$ type :: is a shell builtin
$ help ::::Null command.No effect; the command does nothing.ExitStatus:Always succeeds.
:adalah singkatan true. Mungkin di dalam beberapa shell, truebukan builtin? Keduanya built-in di bash.
Peter Cordes
12
:adalah nama lain untuk true. Keduanya builtin shell dalam bash, tetapi tidak ada /bin/:, hanya a /bin/true. Pengalihan output menyebabkan shell ke open(2)file dengan O_CREAT|O_TRUNC. Jika tidak ada yang tertulis, panjangnya nol.
Menyatukan kedua potongan itu, :> fileadalah idiom yang cukup umum untuk memotong file. Namun, kebanyakan orang akan berusaha membuatnya tidak terlihat aneh dengan menulis : >file.
Karena Anda bertanya dalam komentar tentang baris ke-2, saya akan mengubah komentar saya menjadi jawaban. (Meskipun Anda tidak menanyakan hal ini dalam pertanyaan Anda.)
Baris ke-2 adalah loop yang membaca baris dari otherfileke beberapa variabel bernama. Badan loop digunakan echountuk mencetaknya dengan ;pemisah, bukan spasi putih apa pun yang mereka miliki sebelumnya. fileditutup dan dibuka kembali (untuk ditambahkan) setiap iterasi, karena redirect ada di dalam loop. Menggunakan while ...;do read -r ...;done <otherfile >fileakan menyedot lebih sedikit, dan menghindari kebutuhan untuk memotong file terlebih dahulu. read -rtidak makan \sebagai karakter pelarian.
Pemrosesan teks dalam bash cukup lambat. Bagian yang tidak dapat dihindari: readharus berjalan satu byte pada satu waktu (satu read(2)system call per byte) untuk menghindari overshooting ujung baris. Akan lebih baik menggunakan alat yang tepat untuk pekerjaan itu:
--berarti skrip Anda tidak rusak jika otherfiledinamai sesuatu yang konyol --version.
Mengatur Pemisah Bidang Output ke ;berarti Anda bisa melewati beberapa bidang sebagai argumen untuk dicetak. Shell readmenetapkan seluruh sisa baris dengan spasi putih ke variabel terakhir, tetapi tidak ada cara untuk mengatakan awk untuk hanya dibagi menjadi 5. Jika itu penting, mungkin terus menggunakan bash loop, karena itu merepotkan dalam awk. Perl membuatnya mudah, karena ini splitbisa menggunakan argumen max-field, tapi jauh lebih lambat untuk memulai daripada awk.
Sebenarnya, ternyata tidak terlalu sulit, hanya sebuah regex jelek untuk ditulis. Untuk mendapatkan rest-of-the-line dan bukan $5di awk, pengalihan bidang masih kehilangan spasi asli mereka. Ide layak pertama saya adalah dengan menggunakan gensubdi $0(seluruh baris) untuk menghapus pertama 4 bidang (yaitu non-ruang diikuti dengan spasi), meninggalkan segala sesuatu yang lain:
Saya melakukannya dengan benar pada percobaan pertama, tetapi fakta bahwa saya terkesan dengan diri saya sendiri karena mengatakan sesuatu tentang keterbacaan kode awk itu. >. <
Perhatikan bagaimana ini sama printseperti sebelumnya, tetapi dengan taildi tempat $5.
echo 'A B c DD e f g f'|
awk -vOFS=\; '{ tail = gensub("[[:space:]]*([^[:space:]]+[[:space:]]+){4}", "", 1);
print $1, $2, $4, tail, $3 }'
A;B;DD;e f g f;c
Ini akan lebih mengesankan jika saya bisa menyalin / menempelkan literal dan menunjukkan bahwa ia muncul di output. Ketik satu di bash dengan ^ Q. ctrl-Q berarti Mengutip penekanan tombol berikutnya sebagai karakter literal, karena pengeditan garis gaya emacs bash sama dengan emacs aktual untuk ini.
http://mywiki.wooledge.org/BashFAQ memiliki beberapa hal bermanfaat tentang penulisan skrip dengan cara yang tidak akan merusak data atau nama file apa pun yang Anda masukkan ke dalam skrip.
:>
bukan operator tunggal. Mungkin lebih mudah untuk dipahami jika Anda membacanya sebagai: > file
gantinya.while read A B C D E; do echo "$A;$B;$D;$E;$C"; done < otherfile > file
. Atau lebih baik lagi, mereka seharusnya menggunakan alat yang tepat untuk pekerjaan itu, awk, seperti yang disarankan oleh Peter . Selain itu, Anda hampir selalu ingin menggunakan-r
sakelarread
.Jawaban:
Ada:> dalam baris skrip bash. Apa artinya?
Ini adalah cara pintas untuk mengatakan:
file
tidak ada maka buat yang lain memotongnya menjadi0
byte.Ini berarti Anda dapat yakin bahwa itu
file
ada dan kosong.Anda juga dapat menggunakan
> file
tetapi:> file
lebih portabel.Lihat pertanyaan Stack Overflow Apa Tujuan dari ':' (titik dua) GNU Bash Builtin? untuk informasi lebih lanjut.
sumber
otherfile
dan keecho
merekafile
. Itu juga membuat variabel dari apa pun yang dibacanya ... Jika Anda ingin jawaban yang pasti silakan ajukan pertanyaan Anda sendiri.read
mendapat masukan dari stdin. Dengan sendirinya, itu akan membaca apa yang Anda ketik. Karena stdin telah dialihkan ke<otherfile
maka isiotherfile
"diketik" ke dalam stdin. Jadiread
dapatkan nilai-nilai baris demi baris ke dalam variabel $ A, $ B, $ C, $ D dan $ E.truncate
dari dari coreutils?Sepertinya cara mewah untuk membuat file baru. In
bash
:
adalah perintah nol:>
mengalihkan output:
ke file.sumber
>
dilakukannya:
adalah singkatantrue
. Mungkin di dalam beberapa shell,true
bukan builtin? Keduanya built-in di bash.:
adalah nama lain untuktrue
. Keduanya builtin shell dalam bash, tetapi tidak ada/bin/:
, hanya a/bin/true
. Pengalihan output menyebabkan shell keopen(2)
file denganO_CREAT|O_TRUNC
. Jika tidak ada yang tertulis, panjangnya nol.Menyatukan kedua potongan itu,
:> file
adalah idiom yang cukup umum untuk memotong file. Namun, kebanyakan orang akan berusaha membuatnya tidak terlihat aneh dengan menulis: >file
.Karena Anda bertanya dalam komentar tentang baris ke-2, saya akan mengubah komentar saya menjadi jawaban. (Meskipun Anda tidak menanyakan hal ini dalam pertanyaan Anda.)
Baris ke-2 adalah loop yang membaca baris dari
otherfile
ke beberapa variabel bernama. Badan loop digunakanecho
untuk mencetaknya dengan;
pemisah, bukan spasi putih apa pun yang mereka miliki sebelumnya.file
ditutup dan dibuka kembali (untuk ditambahkan) setiap iterasi, karena redirect ada di dalam loop. Menggunakanwhile ...;do read -r ...;done <otherfile >file
akan menyedot lebih sedikit, dan menghindari kebutuhan untuk memotong file terlebih dahulu.read -r
tidak makan\
sebagai karakter pelarian.Pemrosesan teks dalam bash cukup lambat. Bagian yang tidak dapat dihindari:
read
harus berjalan satu byte pada satu waktu (saturead(2)
system call per byte) untuk menghindari overshooting ujung baris. Akan lebih baik menggunakan alat yang tepat untuk pekerjaan itu:--
berarti skrip Anda tidak rusak jikaotherfile
dinamai sesuatu yang konyol--version
.Mengatur Pemisah Bidang Output ke
;
berarti Anda bisa melewati beberapa bidang sebagai argumen untuk dicetak. Shellread
menetapkan seluruh sisa baris dengan spasi putih ke variabel terakhir, tetapi tidak ada cara untuk mengatakan awk untuk hanya dibagi menjadi 5. Jika itu penting, mungkin terus menggunakan bash loop, karena itu merepotkan dalam awk. Perl membuatnya mudah, karena inisplit
bisa menggunakan argumen max-field, tapi jauh lebih lambat untuk memulai daripada awk.Sebenarnya, ternyata tidak terlalu sulit, hanya sebuah regex jelek untuk ditulis. Untuk mendapatkan rest-of-the-line dan bukan
$5
di awk, pengalihan bidang masih kehilangan spasi asli mereka. Ide layak pertama saya adalah dengan menggunakangensub
di$0
(seluruh baris) untuk menghapus pertama 4 bidang (yaitu non-ruang diikuti dengan spasi), meninggalkan segala sesuatu yang lain:Saya melakukannya dengan benar pada percobaan pertama, tetapi fakta bahwa saya terkesan dengan diri saya sendiri karena mengatakan sesuatu tentang keterbacaan kode awk itu. >. <
Perhatikan bagaimana ini sama
print
seperti sebelumnya, tetapi dengantail
di tempat$5
.Ini akan lebih mengesankan jika saya bisa menyalin / menempelkan literal dan menunjukkan bahwa ia muncul di output. Ketik satu di bash dengan ^ Q. ctrl-Q berarti Mengutip penekanan tombol berikutnya sebagai karakter literal, karena pengeditan garis gaya emacs bash sama dengan emacs aktual untuk ini.
http://mywiki.wooledge.org/BashFAQ memiliki beberapa hal bermanfaat tentang penulisan skrip dengan cara yang tidak akan merusak data atau nama file apa pun yang Anda masukkan ke dalam skrip.
sumber