![잘림 문자를 사용하여 bash 인수 작성](https://linux55.com/image/216214/%EC%9E%98%EB%A6%BC%20%EB%AC%B8%EC%9E%90%EB%A5%BC%20%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC%20bash%20%EC%9D%B8%EC%88%98%20%EC%9E%91%EC%84%B1.png)
\u2263
양쪽에 두 개의 공백으로 구분된 유니코드 문자를 사용하여 bash 함수의 처음 두 인수를 인쇄하고 싶습니다 . 문제는 최종 유니코드가 70열에 표시되어야 한다는 것입니다. 문자 범위가 열 68에 $1
도달 하면 $2
추가 문자가 잘립니다.
1 2 3 V 4 5 6 7
1234567890123456789012345678901234567890123456789012345678901234567890
U FIRST-ARG SECOND-ARG U
U FIRST-ARG-LONGGGGGGGGGGGGGGGG SECOND-ARG U
가능한 최대 너비로 열 번호(예: 34
문자로 설명되는 선택)를 지정할 수 있습니다.V
FIRST-ARG
시작된 cl
합계의 최대 길이입니다 cr
.
local cl=34 cr=30
printf ' \u2263 %.${cl}s %.${cr}s \u2263\n' "$1" "$2"
답변1
은 공백 으로 채워 지고 63으로 잘립니다 bash
.printf
%-63.63s
바이트문자가 아니므로 모든 문자가 싱글바이트가 아닌 이상 형식 지정/정렬에 사용할 수 없습니다. 99.99%의 문자가 여러 바이트를 사용하여 UTF-8로 인코딩됩니다. U+2263 문자는 UTF-8의 경우 3바이트, GB18030의 경우 4바이트로 인코딩됩니다.
ksh93과 마찬가지로 bash ${var:offset:length}
는 문자 수준에서 복사하지만 모든 문자가 단일 너비인 경우에만 작동합니다.
텍스트를 올바르게 정렬하려면 가능한 방법은 다음과 같습니다.
- 문자 표시 너비를 고려하는 패딩/잘림 연산자를 사용하십시오.
- 출력이 터미널에 도달한다고 가정하고 제어 시퀀스를 사용하여 쓰기 위치에 원하는 것을 쓰고 그렇지 않은 것을 삭제하도록 터미널에 지시합니다.
1의 경우 bash 대신 내장 연산자(예: ksh93 또는 zsh)가 있는 셸을 사용할 수 있습니다.
zsh에서:
align() printf ' \u2263 %s \u2263\n' ${(j[ ]mr[63])@}
인수 r[length]
확장 플래그(여기서는 r[length][ ]
공백이 기본 패딩 문자로 축약됨) r
ight는 지정된 길이로 채워지고 m
디스플레이 너비 단위의 길이와 함께 사용됩니다.
또는 나중에 명시한 대로 왼쪽 정렬(및 오른쪽 패딩) $1
및 오른쪽 정렬입니다 .$2
align() printf ' \u2263 %s \u2263\n' "${(mr[31])1} ${(ml[31])2}"
이를 사용하면 ksh93
더욱 간단해집니다.
align() printf ' \u2263 %-63.63Ls \u2263\n' "$1 $2"
%Ls
이와 대조적으로 바이트 %s
가 아닌 문자열을 사용하여 표시 너비에 따라 문자열을 채우고 자릅니다.
또는 왼쪽 $1
과 오른쪽을 정렬합니다 $2
.
align() printf ' \u2263 %-31.31Ls %31.31Ls \u2263\n' "$1" "$2"
입력에 제어 문자가 포함되어 있으면 작동하지 않습니다.
2의 경우 자동 여백을 비활성화하고 전체 텍스트를 쓴 다음 68열로 이동한 다음 " ≣"
나머지를 쓰고 지울 수 있습니다.
am_off=$(tput rmam) am_on=$(tput smam)
col68=$(tput cr; tput cuf 68)
del_to_eol=$(tput el)
align() {
printf ' \u2263 %s\u2263%s\n' "$am_off$1 $2$col68 " "$del_to_eol$am_on"
}
답변2
2개의 긴 매개변수를 얻습니다.
set -- '123456789.123456789.123456789.123456789.' '987654321.987654321.987654321.987654321.'
V를 40으로 설정한다고 가정하면 field1에는 40자가 있고 field2에는 68-40=28자가 있습니다.
cl=40
cr=$((68-cl))
이제 우리는 첫 번째 필드를 왼쪽 정렬하고 두 번째 필드를 오른쪽 정렬하여 인쇄하려고 합니다(긴 인수에서는 보이지 않지만). printf 형식 문자열에서 필드 너비를 설정하는 것만으로는 충분하지 않으며 매개변수의 하위 문자열만 가져와야 합니다.
printf '\u2263 %-*s%*s \u2263\n' "$cl" "${1:0:cl}" "$cr" "${2:0:cr}"
≣ 123456789.123456789.123456789.123456789.987654321.987654321.98765432 ≣
우리는 그것을 볼 수 있습니다
- "123456789.123456789.123456789.123456789.", 첫 번째 매개변수의 처음 40자
- "987654321.987654321.98765432", 두 번째의 처음 28자입니다.
답변3
아? 뭐가 필요하세요?
문제가 문자열 길이를 조작하는 방법이라면 여기에 설명된 문자열 함수를 사용할 수 있습니다. https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Shell-Parameter-Expansion
형식화된 방식으로 무언가를 인쇄해야 하는 경우 C에서와 정확히 동일한 형식을 printf
사용 echo
합니다.printf()
https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#index-printf