Bash는 문자열을 조정하기 위해 후행 공백을 추가합니다.

Bash는 문자열을 조정하기 위해 후행 공백을 추가합니다.

현재 코드는 다음과 같습니다. 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áéíó네 자리에서 실패했습니다.

여기에는 두 가지 다른 문제가 있습니다.

  • 첫 번째는 문자당 사용되는 바이트 수입니다. 예를 들어 need 3는 3자를 9바이트로 만듭니다(printf에 필요한 것). 이 경우 printf는 3자를 9바이트로 계산합니다.
  • 두 번째는 각 문자의 너비입니다. 이들 모두에는 áéíóúüñ2바이트가 필요하며 한 위치 너비(공백과 동일한 너비)입니다. 따라서 printf인쇄 aáéíó( 의 1바이트 a, 나머지 2바이트가 9바이트를 구성함)는 문자 5개에 후행 공백만 포함되므로 총 너비는 6이 됩니다. 즉 공백 4개가 부족합니다.
  • 각 문자는 인쇄할 때 3바이트가 필요 ㉑㉒㉓하지만 문자당 2개의 공백을 사용하므로 문자열을 표시할 때 너비는 6개의 공백이 됩니다.

관련 정보