Linux에서 Bash printf 명령을 사용하는 방법
게시 됨: 2022-06-25 Bash printf
명령을 사용하면 echo
명령이 제공하는 것보다 더 세밀한 제어와 더 많은 서식 옵션을 사용하여 Linux 터미널 창에 쓸 수 있습니다. printf
의 이상한 단점도 유용할 수 있습니다.
터미널에 쓰기
프로그램과 상호 작용하는 가장 기본적인 부분 중 하나입니다. 프로그램은 화면에 무언가를 쓰고, 당신은 그것을 읽습니다. 명령줄 프로그램의 Unix 파생 및 Linux 유지 규칙을 고려하더라도 가능한 한 간결합니다. 많은 경우 문제가 발생한 경우에만 터미널에 씁니다. 사용자에게 무슨 일이 일어나고 있는지, 또는 발생하려고 하거나, 방금 일어난 일을 알려주는 것은 필수적인 프로그래밍 기본 요소입니다.
Bash 셸에는 터미널 창에 텍스트를 쓸 수 있는 echo
명령이 있습니다. 변수를 처리하고 문자열에 포함된 경우 해당 값을 표시할 수 있으며 스크립트나 명령줄에서 사용할 수 있습니다. 그렇다면 왜 printf
가 존재합니까? echo
는 텍스트 쓰기를 다루지 않습니까? 음, printf
는 터미널 창에 문자열을 쓰는 평범한 행위 이상의 기능을 제공합니다. 출력을 매우 유연하게 형식화할 수 있으며 다른 트릭도 있습니다.
Bash printf
명령은 C 언어의 printf
함수를 모델로 하고 있지만 차이점이 있습니다. C를 알고 있다면 이러한 차이점에 주의해야 합니다.
기본 문자열 작성
echo
와 printf
가 터미널에 문자열을 쓸 때 어떻게 다른지 봅시다.
echo 여기에 몇 가지 단어가 있습니다.
printf 여기에 몇 가지 단어가 있습니다
echo
명령은 모든 단어를 인쇄하지만 printf
는 첫 번째 단어만 인쇄합니다. 또한 printf
에 의해 인쇄된 새 줄이 없습니다. 출력은 명령 프롬프트와 맞닿아 있습니다. 그러나 먼저 모든 단어에 대해 printf
가 작동하도록 하려면 먼저 인용해야 합니다.
echo 여기에 몇 가지 단어가 있습니다.
printf "여기에 몇 가지 단어가 있습니다"
그게 낫다. 우리는 모든 단어를 인쇄했지만 여전히 새 줄을 얻지 못했습니다. printf
를 사용하면 요청하는 경우에만 새 줄을 얻을 수 있기 때문입니다. 그것은 고통처럼 보일 수 있지만 하나를 포함할지 여부를 결정할 수 있습니다. printf
가 새 줄을 발행하게 하려면 문자열에 " \n
"을 포함해야 합니다. 이것은 "개행" 이스케이프 시퀀스입니다.
echo 여기에 몇 가지 단어가 있습니다.
printf "여기에 몇 가지 단어가 있습니다\n"
줄 바꿈을 사용할 때도 있고 사용하지 않을 때도 있습니다. 다음은 하나의 printf
문에서 새 줄을 사용하고 다른 문에서는 사용하지 않는 경우입니다.
printf "방법" && printf "괴짜\n"
첫 번째 printf
는 새 줄을 인쇄하지 않기 때문에 두 번째 printf
의 출력은 "How-To" 바로 다음에 같은 줄에 위치합니다. 두 번째 printf
는 \n
을 사용하여 새 줄을 인쇄합니다. 이렇게 하면 인쇄된 텍스트 아래 줄에 명령 프롬프트가 나타납니다.
관련: Linux Bash 스크립트에서 파일을 한 줄씩 처리하는 방법
기타 이스케이프 문자
사용할 수 있는 이스케이프 문자가 몇 가지 더 있습니다. 이미 " \n
"이 실행되는 것을 보았습니다.
- \n : 새 줄로 아래로 이동합니다.
- \r : 캐리지 리턴을 인쇄합니다. 이것은 출력 커서를 현재 줄의 시작 부분으로 다시 보냅니다.
- \t : 탭 문자를 출력합니다.
- \v : 세로 탭 공백을 인쇄합니다.
- \\ : 백슬래시 문자를 인쇄합니다.
- \" : 인용 문자를 출력합니다.
- \b : 백스페이스 문자를 출력합니다.
캐리지 리턴 이스케이프 문자는 커서를 현재 줄의 시작 부분으로 다시 이동합니다.
printf "꿀은 모든 악의 근원입니다\r돈\n"
printf
명령은 왼쪽에서 오른쪽으로 입력을 처리합니다. 문자열은 printf
가 " \r
" 이스케이프 문자를 만날 때까지 일반 텍스트로 인쇄됩니다. 출력 커서가 현재 줄의 시작 부분으로 다시 이동합니다.
문자열 처리는 " \r
" 문자 바로 뒤에 있는 문자로 다시 시작됩니다. 나머지를 처리하면 printf
가 "Money"를 인쇄하여 "Honey"라는 단어를 덮어씁니다.
인용 부호 " "
"는 문자열을 인용하는 데 사용되며 백슬래시 " \
" 문자는 이스케이프 시퀀스를 나타냅니다. 이러한 문자를 인쇄하려면 백슬래시로 이스케이프해야 합니다. 이렇게 하면 printf
가 문자를 리터럴 문자로 처리하도록 지시합니다.
printf "이것은 \tTab이고 따옴표는 \"이며 이 \\는 백슬래시입니다\n"
변수 사용
printf
와 함께 변수를 사용하는 것은 echo
와 함께 변수를 사용하는 것과 매우 유사합니다. 이 환경 변수와 같은 변수를 포함하려면 평소와 같이 달러 기호 " $
"를 앞에 둡니다.
printf "홈 디렉토리: $HOME\n"
관련: Bash에서 변수로 작업하는 방법
형식 문자열
형식 문자열은 출력 형식을 정의하는 문자열입니다. 작동할 형식 문자열에 대한 인수로 텍스트 및 기타 값을 제공합니다.
형식 문자열에는 텍스트, 이스케이프 시퀀스 및 형식 지정 자가 포함될 수 있습니다. 형식 지정자는 문자열, 정수 또는 문자와 같이 예상되는 인수 유형을 printf
에 알려줍니다.
가장 일반적인 형식 지정자입니다. 모두 퍼센트 " %
" 기호가 앞에 옵니다. 백분율 기호를 인쇄하려면 두 개의 백분율 기호 " %%
"를 함께 사용합니다.
- %s : 문자열을 출력합니다.
- %c : 단일 문자를 출력합니다.
- %d : 정수를 출력합니다.
- %f : 부동 소수점 숫자를 출력합니다.
- %u : 부호 없는 정수를 출력합니다.
- %o : 8진수로 값을 출력합니다.
- %x : 값을 16진수로 소문자로 출력합니다.
- %X : 16진수로 값을 대문자로 출력합니다.
- %e : 과학 표기법의 부동 소수점 숫자를 소문자로 인쇄합니다.
- %E : 과학 표기법의 부동 소수점 숫자를 대문자로 인쇄합니다.
- %% : 백분율 "%" 기호를 인쇄합니다.
printf "방법 %s\n" "괴짜"
printf "%s%s %s\n" "방법" "-받는 사람" "괴짜"
첫 번째 명령의 형식 문자열에는 자체 텍스트가 포함되어 있습니다. "Geek" 문자열을 printf
에 대한 인수로 전달합니다. " %s
" 형식 지정자와 일치하고 인쇄됩니다. 형식 문자열과 인수 문자열 사이에는 공백만 있음을 유의하십시오. C에서는 이들을 구분하기 위해 쉼표가 필요하지만 Bash 버전의 printf
에서는 공백을 사용하는 것으로 충분합니다.
두 번째 형식 문자열에는 형식 지정자와 개행 이스케이프 시퀀스만 포함됩니다. 세 개의 문자열 인수는 각각 " %s
" 형식 지정자에 의해 차례로 사용됩니다. 다시 말하지만 C에서는 각 인수 사이에 쉼표를 넣어야 하지만 Bash printf
를 사용하면 이를 잊어버릴 수 있습니다.
다른 유형의 인수를 인쇄하려면 적절한 형식 지정자를 사용하기만 하면 됩니다. 다음은 printf
를 사용하여 만든 빠른 숫자 변환 루틴입니다. 값 15를 10진수, 8진수, 16진수 표기법으로 인쇄합니다.
printf "12월: %d\n10월: %o\n16진수: %x\n" 15 15 15
예제가 덜 복잡해지도록 다시 약간 다듬어 보겠습니다.
printf "16진수: %x\n" 15
우리 대부분은 16진수 값을 대문자로 보고 0x10보다 작은 값을 앞에 0으로 인쇄하는 데 익숙합니다. 대문자 16진수 형식 지정자 " %X
"를 사용하고 백분율 기호 " %
"와 " X
" 문자 사이에 너비 지정자를 넣어 이를 달성할 수 있습니다.
이것은 인자가 인쇄되어야 하는 필드의 너비를 printf
에 알려줍니다. 필드는 공백으로 채워집니다. 이 형식을 사용하면 패딩 없이 두 자리 값이 인쇄됩니다.
printf "16진수: %2X\n" 15
이제 선행 공백이 인쇄된 대문자 값을 얻습니다. 두 개 앞에 0을 놓아서 printf
가 공백 대신 0으로 필드를 채우도록 할 수 있습니다.
printf "16진수: %02X\n" 15
정밀도 지정자를 사용하면 출력에 포함할 소수점 수를 설정할 수 있습니다.
printf "부동 소수점: %08.3f\n" 9.243546
이렇게 하면 깔끔하게 정렬된 출력으로 결과 테이블을 쉽게 생성할 수 있습니다. 이 다음 명령은 Bash printf
의 또 다른 단점도 보여줍니다. 형식 지정자보다 더 많은 인수가 있는 경우 모든 인수가 사용될 때까지 인수가 일괄적으로 형식 문자열에 공급됩니다. 한 번에 처리되는 일괄 처리의 크기는 형식 문자열에 있는 형식 지정자의 수입니다. C에서 printf
함수 호출의 추가 인수는 무시됩니다.
printf "플로트: %8.3f\n" 9.243546 23.665 8.0021
너비 및 정밀도 지정자를 문자열과 함께 사용할 수도 있습니다. 이 명령은 10자 너비의 필드에 문자열을 인쇄합니다.
printf "%10s %d\n" "외투" 7 "신발" 22 "우산" 3
기본적으로 값은 해당 필드에서 오른쪽 정렬됩니다. 왼쪽 정렬하려면 퍼센트 " %
" 기호 바로 뒤에 빼기 기호 " -
"를 사용합니다.
printf "%-10s %d" "외투" 7 "신발" 22 "우산" 3
정밀도 지정자는 인쇄되는 최대 문자 수를 설정하는 데 사용할 수 있습니다. 너비 필드의 한계를 표시하기 위해 콜론 문자 " :
"를 사용하고 있습니다. "Umbrellas"라는 단어가 잘린 방식이 아닙니다.
printf ":%10.6s:\n" "외투" "신발" "우산"
printf ":%-10.6s:\n" "외투" "신발" "우산"
너비 지정자는 인수 로 전달될 수도 있습니다. 숫자 지정자 대신 별표 " *
"를 사용하고 너비를 정수 인수로 전달합니다.
printf "%*s\n" 20 "맨 오른쪽" 12 "가운데" 5 "맨 왼쪽"
기타 트릭과 단점
형식 문자열 내의 형식 지정자는 명령줄에 일반 인수로 제공되거나 표현식 의 출력으로 생성되는지 여부에 관계없이 적절한 유형의 값으로 작동합니다.
이것은 두 숫자의 합을 출력합니다:
printf "23+32=%d\n" $((23+32))
이 명령은 현재 작업 디렉토리의 디렉토리 수를 인쇄합니다.
printf "%d개의 디렉토리가 있습니다\n" $(ls -d */ | wc -l)
이 printf
명령은 다른 명령에 대한 호출에서 반환된 문자열을 인쇄합니다.
printf "현재 사용자: %s\n" $(whoami)
문자열 형식 지정자 " %s
"가 인수와 함께 제공되지 않으면 printf
는 아무 것도 인쇄하지 않습니다.
printf "하나: %s 둘: %s\n" "알파"
문자열 형식 지정자 " %s
"에 실수로 숫자 값이 제공되면 마치 문자열인 것처럼 출력하고 불평하지 않습니다. C printf
로 이것을 시도하지 마십시오. 아주 나쁜 일이 일어날 것입니다. 프로그램이 충돌할 수 있습니다. 그러나 Bash printf
는 불평하지 않고 그것을 처리합니다.
printf "하나: %s 둘: %s\n" "알파" 777
정수 형식 지정자 " %d
"가 인수를 받지 않으면 0을 인쇄합니다.
printf "정수: %d\n"
정수 형식 지정자 " %d
"가 실수로 문자열 인수를 받으면 Bash는 오류 메시지를 인쇄하고 printf
는 0을 인쇄합니다.
printf "정수: %d\n" "7"
유니코드 번호 또는 "코드 포인트"를 사용하여 어색한 기호를 생성할 수 있습니다. 문자 "u" 다음에 유니코드 값을 사용하여 이스케이프됩니다.
printf "유로 기호: \u20AC\n"
인수 문자열에 이스케이프 시퀀스를 포함하려면 " %s
" 문자열 형식 지정자가 아니라 형식 문자열에 " %b
" 형식 지정자를 사용해야 합니다.
printf "%s" "\u20AC\n"
printf "%b" "\u20AC\n"
첫 번째 printf
문은 유니코드 값을 처리하지 않으며 줄 바꿈 이스케이프 시퀀스를 인식하지 못합니다. 두 번째 printf
문은 " %b
" 형식 지정자를 사용합니다. 이렇게 하면 유니코드 문자가 올바르게 처리되고 새 줄이 인쇄됩니다.
관련: ANSI 및 유니코드와 같은 문자 인코딩은 무엇이며 어떻게 다릅니까?
코스용 말
때로는 터미널 창에 일부 텍스트를 echo
하기만 하면 됩니다. 그러나 위치 지정 및 형식 지정을 적용해야 하는 경우에는 printf
가 작업에 적합한 도구입니다.
printf "%b" "타-" "타-" "타-" "그게 다야.\n"