printf가 예상보다 많은 인수를 인쇄하는 이유는 무엇입니까?

printf가 예상보다 많은 인수를 인쇄하는 이유는 무엇입니까?

이 쉘 스크립트는 왜 입력을 두 번 인쇄합니까?

스크립트가 5 이후의 입력을 무시할 것으로 예상했습니다.

스크립트:

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

산출:

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:~$ 

또한 다음 스크립트는 $IFS 설정에 관계없이 작동합니다. 왜?

#! /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"

산출:

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:~$ 

답변1

세 가지 질문이 있습니다.

  1. 그리고read, 변수 이름이 입력 필드보다 작으면 마지막 변수는 구분 기호를 사용하여 줄의 나머지 모든 필드에 바인딩됩니다. 이는 이것이 예상치 못한 첫 번째 예에 $e나타날 것임을 의미합니다.5 6
  2. 모두 $a.. $e참조되지 않기 때문에 해당 값이 변경됩니다.필드 분할. $e" 5 6"을 누르고 있으면 다음으로 확장됩니다.명령의 매개변수입니다.
  3. printf%대체하는 인수만큼 한 번에 많은 인수를 반복적으로 사용하여 모든 인수를 사용합니다 . 이것은문서 속에 묻힌처럼:

    format피연산자는 매개변수 피연산자를 만족시키기 위해 필요한 만큼 여러 번 재사용되어야 합니다. 추가 c또는 s변환 지정자는 빈 문자열 인수가 제공된 것처럼 평가됩니다. 기타 추가 변환 사양은 0 인수가 제공된 것처럼 평가됩니다.

    즉, 사용되지 않는 매개변수가 있는 경우 전체 형식 문자열을 포함하여 처음부터 다시 시작하여 처리합니다. 이는 전체 배열의 형식을 지정하려는 경우에 유용합니다. 예를 들면 다음과 같습니다.

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

    귀하의 printf명령은 $a각 ..에서 하나의 매개변수를 취하고 .. $d에서 많은 매개변수가 남습니다 $e. $e" " 이면 두 개의 루프가 5 6있고 printf두 번째에서는 6포맷이 시작됩니다. 그것이 나왔을 때 5 6 7 8 9 10두 번째 인쇄를 위해 완전히 교체되었습니다.


추가 가상 필드를 추가하고 매개변수 대체를 참조하면 read이러한 모든 상황을 피할 수 있습니다(항상 좋은 생각입니다).

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

그러면 다음이 제공됩니다.

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

dummy모든 추가 필드와 printf예상되는 5개의 매개변수만 가져옵니다.


두 번째 편집 질문에도 비슷한 답변이 있습니다. a공백이 없는 경우에만 값을 가져옵니다. 이는 .. 이 아무것도 확장되지 않음을 IFS의미 하므로 인수는 하나만 얻을 수 있습니다. 형식 문자열에 공백을 대체하지 않고 인쇄합니다("빈 문자열 인수가 제공된 것처럼").$b$eprintf

답변2

 printf "> %s < " 1 2 3

인쇄할 것이다

 > 1 <> 2 <> 3 <

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

인쇄

 > 1 2 <> 3  <

printf형식 문자열을 충족하기 위해 모든 인수를 먹은 다음 모든 인수가 처리될 때까지 반복합니다.

두 번째 스크립트는 $a명령이 다른 반복으로 유출되지 않도록에만 할당되었기 때문에 작동합니다(반복은 하나만 있음).


이 동작은 제공된 텍스트에 설명되어 있습니다 help printf.

...모든 인수를 사용하기 위해 필요에 따라 형식이 재사용됩니다. 형식에 필요한 것보다 인수 수가 적은 경우 추가 형식 사양은 마치 적절한 0 값이나 빈 문자열이 제공된 것처럼 동작합니다. ...

에 의해 승인되었으며http://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html

관련 정보