Bourne 셸 printf는 왜 %s 인자를 반복하나요?

셸 스크립트를 작업할 때 많은 프로그래머는 명령어의 특정 동작에 대해 혼란스러워 하곤 합니다. 그런 경우 중 하나는 Bourne 셸의 printf 함수, 특히 문자열 인자를 사용할 때 발생합니다. printf를 사용하려고 할 때 예상치 못한 출력을 접한 적이 있다면, 당신만 그런 것이 아닙니다! 왜 이런 일이 발생하는지 그리고 그 문제를 해결하는 방법에 대해 알아봅시다.

문제 분석

다음의 간단한 셸 스크립트를 고려해 보세요:

#! /bin/sh
NAME="George W. Bush"
printf "Hello, %s\n" $NAME

이 스크립트를 실행할 때, 출력이 간단히 Hello, George W. Bush일 것이라고 가정할 수 있습니다. 그러나 놀랍게도, 명령줄은 다음과 같은 결과를 반환합니다:

Hello, George
Hello, W.
Hello, Bush

여기서 무슨 일이 벌어지고 있나요?

문제는 셸이 변수를 확장하는 방법에 있습니다. $NAME을 따옴표 없이 사용하면, 셸은 NAME 변수의 내용을 공백으로 나누어 각 부분을 개별 인자로 취급합니다. 따라서 printf는 세 개의 인자: George, W., Bush와 함께 호출됩니다. 이 각각은 개별적으로 처리되므로 여러분이 보는 예상치 못한 동작이 발생합니다.

올바른 방법

이 문제를 완전히 피하려면 변수를 따옴표로 감싸야 합니다. 다음은 수정된 스크립트입니다:

#! /bin/sh
NAME="George W. Bush"
printf "Hello, %s\n" "$NAME"

따옴표의 중요성

$NAME을 따옴표로 감싸면, 셸에 전체 내용 — 공백 포함 — 이 하나의 인자임을 전달합니다. 이것은 공백을 포함하는 문자열에 매우 중요하며, 변수 확장 중에 그것들이 손상되지 않도록 유지합니다.

대안: 왜 echo를 사용하지 않을까요?

사람들은 왜 단순히 printf 대신 echo를 사용하지 않는지 궁금해 할 수 있습니다. 다음은 다른 예제를 사용하여 두 가지를 비교한 것입니다:

#! /bin/sh
FILE="C:\tmp"
echo "Filename: $FILE"

이 스크립트를 실행하면:

Filename: C:    mp

이 동작은 백슬래시와 이스케이프 시퀀스 사용 시 echo에서 발생할 수 있는 문제를 보여줍니다. POSIX echo 사양에 따르면: “새로운 애플리케이션은 echo 대신 printf를 사용하는 것이 권장됩니다.” 이 권장은 예측 가능한 동작과 출력 형식화에서의 printf의 다재다능함을 강조합니다.

결론

요약하자면, 셸 스크립트에서 printf를 사용할 때는 반드시 공백이나 특수 문자가 포함될 수 있는 변수 주위에 큰따옴표를 사용해야 합니다. 이렇게 하면 출력이 예상대로 동작하고 불필요한 놀라움을 막을 수 있습니다. 이러한 작은 조정으로 여러분은 스크립트에서 깨끗하고 제어된 출력을 위해 printf를 자신 있게 활용할 수 있습니다!

이러한 모범 사례를 채택함으로써, 여러분은 더 강력하고 신뢰할 수 있는 셸 스크립트를 작성하게 될 것입니다.