다른 문자로 문자열에서 후행 공백을 패딩


12

hello world20 자 이상 을 출력하고 싶습니다 .

printf "%-20s :\n\n" 'hello world!!'

# Actual output
hello world!!        :

# Wanted output
hello world!!========:

그러나 공백으로 완료하고 싶지 않지만 대신 " = " 로 완료하고 싶습니다 . 어떻게해야합니까?

답변:


9

보다 일반적인 솔루션으로 답변을 업데이트했습니다. 쉘 괄호 확장 만 사용하여 아래의 또 다른 대답을 참조하십시오 pritnf.

$ str='Hello World!'
$ sed -r ':loop; s/ (=*):$/\1=:/; t loop' <<< "$(printf '%-20s:\n' "$str" )"
Hello World!========:

어떻게 작동합니까?

이것은 입력의 끝에 콜론이 뒤 따르는 (=*):$/하나 이상의 공간을 캡처합니다 . 우리는 집합을 그룹으로 일치시키고 그 역 참조가 될 것입니다.=:=\1

함께 :loop우리 레이블라는 정의 loop와 함께 t loop그것은 그 라벨로 이동합니다 s/ (=*):$/\1=:/성공적으로 대체를 수행하고있다;

로 대체되는 부분에서는 \1=:항상 =s 수를 늘리고 콜론 자체를 문자열 끝으로 되돌립니다.


1
입력의 단어 수에 따라 플래그를 조정해야합니까?
user1686 년

@ grawity 나는 지금 일반적인 솔루션에 대한 답변을 업데이트했습니다.
αғsнιη

20
filler='===================='
string='foo'

printf '%s\n' "$string${filler:${#string}}"

준다

foo=================

${#string}값의 길이이고 $string, 그리고 ${filler:${#string}}의 문자열 인 $filler오프셋으로부터 ${#string}전방.

출력의 총 너비는 $filler또는 최대 너비의 너비입니다 $string.

를 사용하는 시스템에서 필러 문자열은 다음을 jot사용하여 동적으로 만들 수 있습니다.

filler=$( jot -s '' -c 16 '=' '=' )

( =한 줄 에 16 ). GNU 시스템은 다음을 사용할 수 있습니다 seq.

filler=$( seq -s '=' 1 16 | tr -dc '=' )

다른 시스템은 Perl 또는 다른 빠른 방법으로 문자열을 동적으로 생성 할 수 있습니다.


printf모든 시스템에서 거의 사용 가능한 필터를 생성하고 쉘과 같은 괄호 확장을 사용하지 bash/szh않습니까?
αғsнιη

@sddgob printf+ 중괄호 확장으로 bash어떻게 하시겠습니까?
Kusalananda

확인하시기 바랍니다 unix.stackexchange.com/a/399059/72456
αғsнιη

17
printf "%.20s:\n\n" "$str========================="

%.20s문자열 잘림 형식은 어디에 있습니까?


2
이것은 IMHO, 내 것보다 더 나은 솔루션입니다. 형식 문자열에 대한 간단한 설명 만 있으면됩니다.
Kusalananda

12

그것을하는 한 가지 방법 :

printf "====================:\r%s\n\n" 'hello world!!'

6
하아! 그것은 영리한 속임수입니다! 그러나 실제로 인쇄 ====================\rhello world됩니다. OP가 이것을 저장하고 화면에 인쇄하는 것이 아니라면 문제가 될 수 있습니다.
terdon

또한 echo -e '=================\rHello World!!'@terdon이 지적한 것과 같은 문제가 있습니다.
αғsнιη

1
@ αғsнιη echo지원하는 경우에만 -e. 여러 가지 이유로 printf거의 항상보다 낫습니다 echo.
Satō Katsura

5

펄 접근 방식 :

$ perl -le '$k="hello world!!"; while(length($k)<20){$k.="=";} print "$k\n"'
hello world!!=======

또는 @SatoKatsura는 의견에서 지적했습니다.

perl -le '$k = "hello world!!"; print $k, "=" x (20-length $k), "\n"'

UTF 멀티 바이트 문자를 지원해야하는 경우 다음을 사용하십시오.

PERL_UNICODE='AS' perl -le '$k = "hello world!!"; print $k, "=" x (20-length $k), "\n"'

쉘에서 동일한 아이디어 :

v='hello world!!'; while [ ${#v} -lt 20 ]; do v="$v""="; done; printf '%s\n\n' "$v"

루프가 필요하지 않습니다 : perl -le '$k = "hello world!!"; print $k, "=" x (20-length $k), "\n"'. 그러나 멀티 바이트 문자가 관련되면이 (및 지금까지 게시 된 다른 모든 솔루션)가 중단됩니다.
Satō Katsura

@ SatōKatsura ooh, 그래, 깔끔합니다! 고맙습니다. 그리고 예, UTF 멀티 바이트 문자에서 가능한 실패에 대한 고지 사항을 추가하려고 생각했지만이 문맥에서 불필요 한 합병증이 될 것이라고 생각했습니다.
terdon

perl6멀티 바이트 문자로도 올바르게 수행 할 수있는 방법이 있다고 생각 합니다. 그러나 반면 perl6에 여러 가지면에서 성가신 일입니다.
Satō Katsura

@ SatōKatsura 잘, 이런 종류의 간단한 일을 위해, 그것은 단지 설정하기에 충분해야합니다 PERL_UNICODE='AS'. 예를 들어, 5 printf '%s' nóóös | perl -nle 'print length($_)'printf '%s' nóóös | PERL_UNICODE='AS' perl -nle 'print length($_)'인쇄 하는 동안 8을 인쇄합니다 ( "올바른").
terdon

5

또 다른 방법은 사용하고 printf의해 첫 번째 문자 패딩 패턴을 명령 및 생성 Shell Brace Expansion(당신은 넣을 수 있습니다 말을 수 ≥ 서식 영역 당신이 인쇄하려는와 {1..end})과의 모든 첫 번째 문자를 얻을 수 %.1s있는 =유일한 처음 20 문자 길이를 인쇄 한 후 s와 그 지역 %.20s. 이것은 문자 / 단어를 복제하지 않고 반복하는 더 좋은 방법입니다.

printf '%.20s:\n' "$str$(printf '%.1s' ={1..20})"
Hello World!!=======:

설명 :

일반적으로 Brace Expansion 으로 {1..20}인쇄하면 쉘 이 다음과 같이 확장 됩니다.

printf '%s ' {1..20}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 

그것에 등호를 추가하면 ={1..20}쉘은 다음과 같이 확장됩니다.

printf '%s ' ={1..20}
=1 =2 =3 =4 =5 =6 =7 =8 =9 =10 =11 =12 =13 =14 =15 =16 =17 =18 =19 =20 

그리고 printf '%.1s'이것이 실제로 의미하는 것은 printf '%WIDE.LENGTH', 기본 너비 로 위의 길이 중 하나만 인쇄하는 것 입니다. 결과는 20 회만 반복됩니다.1 =

이제 printf '%.20s:\n'우리는 20 길이의 길이 만 인쇄 $str하고 길이가 $str<20이면 나머지는 =공백 대신 채워지 는 생성에서 가져옵니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.