문자열을 특정 길이로 채우기 위해 선행 문자를 추가하는 방법은 무엇입니까?
문자열이 20자보다 짧은 경우 문자열 앞에 0을 추가하고 싶다고 가정해 보겠습니다.
printf '%020s\n' "$line"
그러나 이는 0과 같은 다른 어떤 것도 아닌 선행 공백으로 문자열을 채웁니다.
문자열은 숫자와 기타 문자를 포함하는 임의의 문자열일 수 있습니다.
printf '%020i' $number
문자열을 or 에 대한 숫자 + 나머지로 나누고 싶지 않습니다 printf '%020d $number'
.
내 현재 출력은 다음과 같습니다
shortstring
내가 원하는 출력은 다음과 같습니다.
000000000shortstring
답변1
수동으로 채워주시면 됩니다. POSIX 도구 사용을 고집한다면 이보다 더 간단한 해결책은 없다고 생각합니다.
while [ ${#line} -lt 20 ]; do
line=0$line
done
또는
n=${#line}
while [ $n -lt 20 ]; do
printf '0'
n=$((n-1))
done
printf "$line\n"
물론 zsh에는 해당 구문이 있습니다. 위의 코드 조각과 달리 이 코드 조각은 문자열이 20자를 초과하는 경우 문자열을 자릅니다. 자르지 않으려면 문자열 끝을 추가할 수 있습니다.
print -r ${(l:20::0:)line}
print -r ${(l:20::0:)line}${line:20}
답변2
@Gnouc가 이미 지적했듯이 이미 절반쯤 왔습니다.
line='some chars'
printf '%0'$((20-${#line}))'d%s\n' 0 "$line"
###OUTPUT###
0000000000some chars
물론 줄이 20자를 초과하더라도 여전히 0을 얻게 됩니다.만약에 printf
-
형식 문자열의 대시를 올바르게 처리할 수 없기 때문에 오류가 발생하지 않습니다.(이것은 분명히 더 가능성이 높은 시나리오입니다). 하지만 이는 처리하기 쉽습니다.
printf "%.$((((l=20-${#line})>0)*l))d%s\n" 0 "$line"
형식 문자열은 printf
'를 사용합니다.%.
정확한%.0d
플래그는 표시된 길이에 대해 분수 인수를 0으로 채웁니다. 그렇지 않으면 null 또는 null 정밀도의 경우 %.d
앞에 오는 0을 표시된 숫자로 자릅니다. 이와 같이:
printf '#%.0d%c%.5d' 0000000 ':separator' 4
#:00004
(참고: 이 %c
형식은 연관된 인수의 첫 번째 문자를 인쇄합니다)
산술 $((
표현식은 ))
먼저 var를 $l
20 마이너스로 설정한 다음 각각 0보다 작거나 크면 0 또는 1로 평가하고 ${#line}
마지막으로 이를 곱합니다. 따라서 20-가 0보다 작으면 이렇게 하고, 0보다 크면 이렇게 합니다.$l
$l
${#line}
$((0*l))
$((1*l))
이 방법으로 당신은언제나20과 의 차이와 동일한 수의 선행 0만 인쇄합니다 ${#line}
. 이와 같이:
line='some chars'
printf "#%.$((((l=20-${#line})>0)*l))d%s\n" 0 "$line"
#0000000000some chars
그리고...
line='some chars'
printf "#%.$((((l=4-${#line})>0)*l))d%s\n" 0 "$line"
#some chars
당신은 같은 것을 사용할 수 있습니다%.
정확한fields 유형에도 동일하게 적용됩니다 s
. 예를 들면 다음과 같습니다.
line='some chars'
printf "#%.$((((l=4-${#line})>0)*l))d%.4s\n" 0 "$line"
#some
...필요에 따라 잘라냅니다.
다음은 루프입니다. 다음은 5번 반복됩니다.
line=
until line=fivec$line; [ $((l)) -lt 0 ]
do printf "#%.$((((l=20-${#line})>0)*l))d%s\n" 0 "$line"
done
#000000000000000fivec
#0000000000fivecfivec
#00000fivecfivecfivec
#fivecfivecfivecfivec
#fivecfivecfivecfivecfivec
표시된 0은 쉘 변수의 값에 전혀 포함되지 않으며(물론) $line
형식 문자열이 지시하는 대로 자동으로 생성된다는 점에 주목할 가치가 있습니다.printf
더 정밀한 동일한 루프는 다음과 같습니다 %.20s
.
line=
until line=fivec$line; [ $((l)) -lt 0 ]
do printf "#%.$((((l=20-${#line})>0)*l))d%.20s\n" 0 "$line"
done
#000000000000000fivec
#0000000000fivecfivec
#00000fivecfivecfivec
#fivecfivecfivecfivec
#fivecfivecfivecfivec
그것으로 할 수 있는 또 다른 일은 정말 재미있습니다. printf
0을 동적으로 생성하는 기능을 결합 하면 $IFS
원하는 만큼 문자열을 사용할 수 있습니다. 예를 들면 다음과 같습니다.
IFS=0 ; printf '10 lines\n%s' $(printf %010d) ; unset IFS
###OUTPUT###
10 lines
10 lines
10 lines
10 lines
10 lines
10 lines
10 lines
10 lines
10 lines
10 lines
답변3
%s
문자열 형식 사양입니다. 제로 패딩만디지털 변환을 위해 존재한다고 정의됨:
0d, i, o, u, x, .다른 변환의 경우 동작이 정의되지 않습니다.
$line
숫자인 경우 다음을 사용하십시오.
printf '%020i\n' $line
원하는 결과(또는 다른 숫자 형식 지정자 중 하나)를 얻으려면 값이 더 복잡하지만 숫자로 시작하는 경우 다음을 사용할 수 있습니다.
printf '%020i %s\n' $num $restofline
숫자와 문자열을 한번에 결합해보세요.
답변4
사용할 수 있는 경우 perl
:
$ perl -e 'print sprintf "%020s\n","shortstring"'
000000000shortstring
보다 일반적인 경우:
$ perl -e 'print sprintf "%020s\n",shift' shortstring
000000000shortstring
$ perl -e 'print sprintf "%020s\n", $_ for @ARGV' shortstring qwerty
000000000shortstring
00000000000000qwerty
노트
일부 플랫폼에서는 적어도 를 AIX
사용할 때 앞에 0을 사용하여 출력 문자열의 형식을 지정할 수 있으며 GNU gcc
컴파일할 때 경고가 표시됩니다.
$ cat test.c
#include <stdio.h>
int main() {
printf("%08s\n", "qwerty");
return 0;
}
그 다음에:
$ gcc -Wall test.c
test.c: In function ‘main’:
test.c:4:5: warning: '0' flag used with ‘%s’ gnu_printf format [-Wformat]
이를 사용하고 싶지 않다면 다음을 perl
시도해 보세요.
$ line=shortstring
$ printf "%0$((20-${#line}))d%s" 0 $line
000000000shortstring
문자열 길이가 20보다 큰 경우 이 메서드는 이를 처리할 수 없습니다. @mikeserv 응답을 사용하여 문제를 처리하거나 이전에 확인하는 데 사용할 수 있습니다 printf
.