Bash'daki bu garip sembol “:>” ne anlama geliyor?


47

Bir komut dosyasında bir şey buldum, ancak ana komut dosyasına ait değil. Orada :>bir çizgide.

Bana ne anlama geldiğini açıklar mısın?

:> file
while read A B C D E; do echo "$A;$B;$D;$E;$C" >> file; done < otherfile

6
Önemli :>olan tek bir operatör değil. Bunun : > fileyerine okursanız anlaşılması daha kolay olabilir .
jpfx1342 18:

Bu senaryoyu yazmaya kişinin dosyaya döngünün çıkışını yönlendirildi gerekirdi anlamına gelir: while read A B C D E; do echo "$A;$B;$D;$E;$C"; done < otherfile > file. Daha da iyisi, Peter'in önerdiği gibi iş için doğru aracı kullanmalıydılar . Bir kenara, neredeyse her zaman -ranahtarı ile kullanmak istersinizread .
Tom Fenech

Dışardaki bash, karga için gülen olur.
smci

Yanıtlar:


46

Vardı:> bir bash betiğinin satırında. Bunun anlamı ne?

:> file

Bu, şöyle demenin kısa bir yoludur:

  • Eğer fileyoksa, onu yaratın ya da onu 0bayt olarak kısaltın.

Bu, filevar olduğundan ve boş olduğundan emin olabileceğiniz anlamına gelir .

Ayrıca kullanabilirsiniz, > fileancak :> filedaha taşınabilir.

Yığın Taşması sorusuna bakın ':' (Kolon) GNU Bash Builtin Amacı Nedir? daha fazla bilgi için.


İkinci satırı anlamıyorum. Okunan değişkenleri okudum. Komuta yankısı da garip. Açıklar mısın
diego9403 15

Ben Unix uzmanı değilim ama ikinci satır bir şeyler okur düşünmek otherfileve echoonları dışarı s file. Aynı zamanda okuduğu her şeyden değişkenler yapar ... Kesin bir cevap istiyorsanız, lütfen kendi sorunuzu sorun.
DavidPostill

2
@ diego9403: readstdin'den girdi alır. Kendi başına yazdığın şeyi okuyacaktı. Stdin yeniden yönlendirildiğinden beri <otherfileiçeriği otherfilestdin içine "yazılır". Böylece read, değerleri sırayla $ A, $ B, $ C, $ D ve $ E değişkenlerine alır.
Slebetman

Yani bu truncateçekirdek çekirdeklerden daha belirsiz bir alternatif mi?
Federico Poloni

1
@PeterCordes "Nadir" dediği gibi "belirsiz" demek istemedim, fakat "okuyucuya daha az açık" olduğu gibi.
Federico Poloni

29

Yeni bir dosya oluşturmanın süslü bir yolu gibi görünüyor. Gelen bash :boş komut şudur:

$ type : 
: is a shell builtin 
$ help : 
:: :
    Null command.

    No effect; the command does nothing.

    Exit Status:
    Always succeeds.

>çıktısını :bir dosyaya yönlendirir .


2
Zaten varsa dosyayı da kısaltacaktır ...
DavidPostill

2
evet, bu ne >yapar
Arkadiusz Drabczyk

2
:için steno true. Muhtemelen bazı mermilerde, trueyerleşik değil mi? Her ikisi de bash içinde yerleşiklerdir.
Peter Cordes

12

:için başka bir isim true. Her ikisi de bash'deki kabuk yapılarıdır, ama hayır /bin/:, sadece a /bin/true. Çıktı yönlendirme, kabuğun open(2)dosyaya gitmesine neden olur O_CREAT|O_TRUNC. Hiçbir şey yazılmazsa, sıfır uzunlukta kalır.

Bu iki parçayı bir araya getirmek, :> filedosyaları kesmek için oldukça yaygın bir deyimdir. : >fileYine de çoğu insan daha az garip görünmeye çalıştı .


2. satır hakkında bir yorumda bulunduğunuzdan, yorumlarımı bir cevaba dönüştüreceğim. (Sorunuzda bunu sormamış olsanız bile.)

2. satır, satırları otherfileadlandırılmış değişkenlere okuyan bir döngüdür . Döngü gövdesi, daha önce sahip oldukları boşluklardan ziyade ayırıcılarla echoyazdırmak için kullanır ;. fileher yinelemede kapatılır ve yeniden açılır (ekleme için), çünkü yönlendirme döngü içindedir. Kullanmak while ...;do read -r ...;done <otherfile >filedaha az emer ve önce dosyayı kesmek zorunda kalmaz. kaçış karakteri olarak read -ryemek yemiyor \.

Bash'taki metin işleme oldukça yavaştır. Bunun bir kısmı kaçınılmaz: Bir satırın sonunu aşmamak için her readdefasında bir bayt ( read(2)bayt başına bir sistem çağrısı) gitmek zorunda. İş için doğru aracı kullanmak daha iyi olacaktır:

awk -vOFS=';' '{ print $1, $2, $4, $5, $3 }' -- otherfile  >file

--otherfileaptalca bir şey olarak adlandırılırsa betiğinizin kırılmadığı anlamına gelir --version.

Çıktı Alanı Ayırıcısını ayarlamak, ;yazdırmak için yalnızca birden çok alanı iletebileceğiniz anlamına gelir. Shell read, satırın geri kalanının tamamını beyaz boşluk ile son değişkene atar, ancak awk'ye yalnızca 5'e ayrılmasını söylemenin bir yolu yoktur. Perl bunu kolaylaştırır, çünkü splitmax-field argümanını alabilir, ancak başlamak için awk'den çok daha yavaştır.

Aslında, o kadar da zor değil, sadece çirkin bir regex yazmak oldu. $5Awk yerine satırın geri kalanını almak için , alanlar üzerinde dolaşmak orijinal boşluklarını hala kaybeder. Benim ilk canlı bir fikir kullanmaktır gensubüzerinde $0kalan her şeyi bırakarak (yani olmayan uzay boşluğundan sonra) ilk 4 alanlarını kaldırmak için (tam çizgi):

awk -vOFS=';' '{ tail = gensub("[[:space:]]*([^[:space:]]+[[:space:]]+){4}", "", 1); print $1, $2, $4, tail, $3 }' -- otherfile >file

İlk denemede doğru yaptım, ama bunun için kendimden etkilendim gerçeği, bu awk kodunun okunabilirliği hakkında bir şeyler söylüyor. >. <

Daha printönce olduğu gibi, ancak bunun yerine nasıl olduğuna taildikkat edin $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

Değişmezi kopyalayıp / yapıştırabilir ve çıktıda ortaya çıktığını gösterebilseydim bu daha etkileyici olurdu. ^ Q ile bash içinde bir tane yazın. ctrl-Q Bir sonraki tuşa basmaya hazır bir karakter olarak alıntı yapın, çünkü bash emacs tarzı çizgi düzenleme işlemi bunun için gerçek emaclerle aynıdır.

http://mywiki.wooledge.org/BashFAQ , senaryoda attığınız veri veya dosya adlarından bağımsız olarak, komut dosyası oluşturma konusunda bazı yararlı şeyler içerir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.