현재 코드는 다음과 같습니다. x=${y:0:40}
문자열 길이를 40자로 제한합니다. 문자열이 40자 미만인 경우 후행 위치를 공백으로 채울 수 있습니까?
그렇다면 내y="very short text"
나는 내 것이 y
다음과 같기를 원합니다:
y="매우 짧은 텍스트(+25개의 후행 공백)"
답변1
당신은 시도해야합니다 printf
:
printf '%-40s' "$y"
답변2
이러한 문자가 모두 단일 바이트인 경우, 즉 로케일의 문자 집합이 단일 바이트(예: iso8859-1)이거나 로케일의 문자 집합은 UTF-8이지만 텍스트는 ASCII 전용인 경우 다음을 수행할 수 있습니다.
printf -v y %-40.40s "$y"
여기에는 잘림과 패딩이 포함됩니다.
그렇지 않은 경우 언제든지 40개의 공백을 추가하고 원하는 방법을 사용할 수 있습니다 ${y:0:40}
.
printf -v pad %40s
y=$y$pad
y=${y:0:40}
zsh
전용 왼쪽 및 오른쪽 패딩 연산자가 있습니다.
y=${(r:40:)y}
(절단도 수행됩니다). zsh
개수 printf
는 바이트가 아닌 문자 단위(또는 매개변수 확장 플래그도 사용되는 경우 문자 단위의 표시 너비를 기준으로 함 m
)이므로 bash
위의 문제는 발생하지 않습니다. 그러나 zsh
이 옵션을 사용하려면 버전 5.3 이상이 필요합니다 -v
.
당신은 또한 볼 수 있습니다이 관련 질문에 대한 답변문자 너비가 다른 경우 자세한 내용을 알아보세요.
답변3
순수한 bash
:
ten=" "
forty="$ten$ten$ten$ten"
y="very short text"
y="${y:0:40}${forty:0:$((40 - ${#y}))}"
echo "'${y}'"
방법은 각 문자열을 자르고 0-40 공백을 추가하는 것입니다.
출력(작은따옴표 위치 참고):
'very short text '
답변4
일반적인 사용 조언은 printf
잘못되었습니다. 문자가 아닌 바이트를 계산합니다. 문자를 올바르게 계산하더라도(대부분의 경우)
배열이 있는 쉘로만 사용이 제한됩니다.${var:start:length}
더 나은 계산 방법은 ${#var}
계산해야 하는 문자에 따라 결정됩니다.
$ for var in 1 123 ΐΐΐ ᾂᾂ "㉑㉒㉓" aáéí;
> do
> printf '|%s%*s|\n' "$var" "$((10-${#var}))" "";
> done
|1 |
|123 |
|ΐΐΐ |
|ᾂᾂ |
|㉑㉒㉓ |
|aáéí |
그러나 문자열 길이를 자르는 유일한 이식 가능한 방법은 grep을 사용하는 것입니다.
#!/bin/sh
n=${1:-10}
for str in 1 123 123456789012 ΐ ΐΐΐ ΐΐΐΐΐΐΐΐΐΐ ΐΐΐΐΐΐΐΐΐΐΐΐΐΐΐΐΐΐΐΐ ᾂᾂᾂᾂᾂ "㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚" aáéíóúüñm
do
str=$str$(printf '%*s' "$n" "") # pad with `n` spaces.
var=$(echo "${str}"|grep -Eo "^.{1,$n}") # limit length to `n`
printf '|%s|\n' "${var}"
done
다음을 인쇄합니다.
|1 |
|123 |
|1234567890|
|ΐ |
|ΐΐΐ |
|ΐΐΐΐΐΐΐΐΐΐ|
|ΐΐΐΐΐΐΐΐΐΐ|
|ᾂᾂᾂᾂᾂ |
|㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚|
|aáéíóúüñm |
반올림된 숫자는 너비가 두 배입니다. 여전히 10개의 문자가 있지만 너비의 두 배를 차지합니다. 이것은 일부 쉘에서 사용될 수 있습니다 var=${str:0:n}
.
인쇄 기능
printf의 구현은 일반적으로 POSIX 사양에 따라 바이트 계산으로 제한됩니다. 문자당 1바이트인 ASCII 문자 또는 기타 문자에는 문제가 없습니다. 그러나 대부분의 다른 국제 인사들은 이렇게 합니다.$ printf '|%-10.9s|..\n' 1234567890 ΐ U+0390 ᾂ U+1F82 "㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚" aáéíóúüñm
|123456789 |..
|ΐ |..
|U+0390 |..
|ᾂ |..
|U+1F82 |..
|㉑㉒㉓ |..
|aáéíó |..
printf는 다음 형식으로 10자 공간에 9자를 인쇄해야 합니다 %10.9s
. 그것은 정확히 그렇게 합니다 1234567890
. 숫자를 9에서 잘라서 10개의 공백에 인쇄합니다 |123456789 |..
. 그런데 ΐ
한 자리에서 실패하고, ᾂ
두 자리에서 실패하고, ㉑㉒㉓
세 자리에서 실패하고, 결국 aáéíó
네 자리에서 실패했습니다.
여기에는 두 가지 다른 문제가 있습니다.
- 첫 번째는 문자당 사용되는 바이트 수입니다. 예를 들어
㉑
need3
는 3자를 9바이트로 만듭니다(printf에 필요한 것). 이 경우 printf는 3자를 9바이트로 계산합니다. - 두 번째는 각 문자의 너비입니다. 이들 모두에는
áéíóúüñ
2바이트가 필요하며 한 위치 너비(공백과 동일한 너비)입니다. 따라서printf
인쇄aáéíó
( 의 1바이트a
, 나머지 2바이트가 9바이트를 구성함)는 문자 5개에 후행 공백만 포함되므로 총 너비는 6이 됩니다. 즉 공백 4개가 부족합니다. - 각 문자는 인쇄할 때 3바이트가 필요
㉑㉒㉓
하지만 문자당 2개의 공백을 사용하므로 문자열을 표시할 때 너비는 6개의 공백이 됩니다.