Printf neden beklenenden daha fazla argüman yazdırıyor?


9

Bu kabuk komut dosyası yazdırma girişleri neden iki kez giriliyor?

Senaryo 5 sonra girdi yoksay bekleniyor.

Senaryo:

#! /bin/bash
echo "Enter 5 words : "
read  a b c d e 
printf "> %s %s %s %s %s <" $a $b $c $d $e

Çıktı:

user@linux:~$ pico ifs2.sh
user@linux:~$ ./ifs2.sh
Enter 5 words : 
1 2 3 4 5 
> 1 2 3 4 5 <user@linux:~$ ./ifs2.sh
Enter 5 words : 
1 2 3 4 5 6
> 1 2 3 4 5 <> 6     <user@linux:~$ ./ifs2.sh
Enter 5 words : 
1 2 3 4 5 6 7 8 9 0
> 1 2 3 4 5 <> 6 7 8 9 0 <user@linux:~$ 

Ve aşağıdaki komut dosyası $ IFS olarak ayarlanmış olursa olsun çalışır. Neden?

#! /bin/bash    
old="$IFS"
IFS=":"
echo "IFS = $IFS"
echo "Enter 5 words : "
read  a b c d e 
printf "> %s %s %s %s %s <" $a $b $c $d $e    
IFS="$old"

Çıktı:

user@linux:~$ ./ifs2.sh
IFS = :
Enter 5 words : 
1 2 3 4 5  
> 1 2 3 4 5      <user@linux:~$ ./ifs2.sh
IFS = :
Enter 5 words : 
1 2 3 4 5
> 1 2 3 4 5     <user@linux:~$ ./ifs2.sh
IFS = :
Enter 5 words : 
1:2:3:4:5
> 1 2 3 4 5 <user@linux:~$ 

bir format belirleyicisiyle ilişkilendirilmiş kaçışla printfistediğiniz zaman durun . Gibi:\c%bprintf %s%\ d%b thing 3 "${var+\cquit printing if set}\nelse do a newline" and 0 keep\ going.
mikeserv

Yanıtlar:


18

Üç sorununuz var:

  1. İle read, girişteki alanlardan daha az değişken adı varsa, son değişken sınırlayıcılarla birlikte satırda kalan tüm alanlara bağlanır. Bu , ilk beklenmedik örneğinize $egirdiği anlamına gelir 5 6.
  2. Tüm Çünkü $a.. $eişlem görmeyen, kendi değerlerini geçmesi alan bölme . Eğer $e"tutan 5 6" o zaman genişler iki komuta argüman.
  3. printftüm argümanlarını, aynı anda %ikame olduğu kadar çok argüman kullanarak tekrar tekrar tüketir . Bu, dokümantasyona şu şekilde gömülür :

    formatİşlenen argümanı işlenen tatmin etmek sıklıkta gerektiği şekilde yeniden yapılacaktır. Herhangi bir ekstra cveya sdönüşüm belirteci boş bir dize argümanı sağlanmış gibi değerlendirilir; diğer ekstra dönüşüm spesifikasyonları sıfır argümanı verilmiş gibi değerlendirilir.

    Başka bir deyişle, kullanılmayan argümanlar varsa, yeniden başlar ve tüm biçim dizesi de dahil olmak üzere bunları baştan başlatır. Bu, tüm diziyi biçimlendirmek istediğinizde kullanışlıdır, örneğin:

    printf '%b ' "${array[@]}"

    Sizin printfkomut birer argüman alır $a.. $dve sonra ancak birçok arta kalan $e. $e" 5 6" Olduğunda , printfiki tane vardır, ikincisi 6biçimlendirmeye başlar. O geldiğinde 5 6 7 8 9 10ikinci baskı için değiştirmelerin tam yelpazesine sahiptir.


Bunlara fazladan bir kukla alan ekleyerek readve parametre değişikliklerinizi (bu her zaman iyi bir fikirdir) alıntılayarak bunların tümünü önleyebilirsiniz :

read  a b c d e dummy
printf "> %s %s %s %s %s <" "$a" "$b" "$c" "$d" "$e"

Bu şunları verecektir:

Enter 5 words : 
1 2 3 4 5 6 7 8 9 10
> 1 2 3 4 5 <

dummytüm ekstra alanları printfalır ve yalnızca beklediğiniz beş argümanı alır.


İkinci düzenlenmiş sorunuzun benzer bir yanıtı var: yalnızca boşluğu olmadığı azaman bir değer alır IFS. Bu demek oluyor ki $b.. $ehiçbir şeye genişleme, bu yüzden printfsadece tek bir argüman alır. Biçim dizesindeki boşluklarınız, aralarında hiçbir şey değiştirilmeden yazdırılır ("boş bir dize bağımsız değişkeni sağlanmış gibi").


Yine "$ a" ..... "$ e" kullanarak 2. komut dosyası test. İkinci komut dosyası aynı sorunu tekrar veriyor.

3
Alıntı yapmak ikinci senaryoda bir fark yaratmayacaktır. tek bir dize olarak adeğere sahiptir ve 1 2 3 4 5bir kerede değiştirilir.
Michael Homer

6
 printf "> %s < " 1 2 3

yazdıracak

 > 1 <> 2 <> 3 <

  printf "> %s %s <" 1 2 3

baskılar

 > 1 2 <> 3  <

printf biçim argümanını karşılamak için tüm argümanları alır ve tüm argümanlar işlenene kadar tekrar eder.

İkinci komut dosyaları çalışır, çünkü yalnızca $ahiç atanır ve bu nedenle komut ek yinelemelere taşmaz (yalnızca bir yineleme vardır).


Bu davranış aşağıdakilerle sağlanan metinde belgelenmiştir help printf:

... Biçim, tüm bağımsız değişkenleri tüketmek için gerektiği şekilde yeniden kullanılır. Biçimin gerektirdiğinden daha az bağımsız değişken varsa, fazladan biçim belirtimleri, uygunsa, sıfır değeri veya boş bir dize sağlanmış gibi davranır. ...

ve zorunluluktan ötürü http://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html


Bu davranış neden? belgelenmiş mi?
Shiplu Mokaddim

1
@Shiplu, davranışın nerede belgelendiği ve davranışı gerektiren standart hakkında bir paragraf ekledi.
PSkocik
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.