printf 명령을 사용하여 N 번 문자 쓰기


12

Linux에서 문자를 반복하는 다음 명령을 찾았습니다.

printf 'H%.0s' {1..5000} > H.txt

예를 들어 시간 H을 반복 하고 싶습니다 5000. 여기서 무엇을 %.0s의미합니까?


tcsh또는 zsh, repeat 5000 printf H이해하기 쉽다. 로 perl: print "H" x 5000(즉주의 {1..5000}에서 영감을 zsh을 연산자 perl의 ' 1..5000하나 나중에 경우 ksh93과 bash에 의해 복사)
스테판 Chazelas가

예, 작동하지만 더 큰 반복을 위해 많은 리소스를 사용하려면 Stéphane Chazelas의 제안을 따르십시오
Skaperen

1
나는이 명령을 수행합니다yes H|head -5000|tr -d '\012'
Skaperen

dd if=/dev/zero bs=5000 count=1 | tr '\0' H
kojiro

@Skaepren :yes H| head -n 2500| tr \\n H
mikeserv

답변:


20

이 명령은 쉘이 5000 개의 인수를 생성 printf한 후 전달하여 무시합니다. 꽤 빠를 수도 있지만 어떤 것에 비해 쉘은 여전히 ​​모든 문자열을 args로 생성 하고 구분해야합니다 .

쉘이 처음 5000까지 반복 될 때까지 생성 된 H를 인쇄 할 수 없다는 사실 외에도,이 명령은 숫자 문자열 인수를 저장하고 H 를 printf 더하는 데 필요한 모든 비용을 메모리에 소모합니다 . 간단하게 할 수있는 것처럼 :

printf %05000s|tr \  H

... 5000 개의 공백 문자열을 생성합니다. 적어도 적어도 하나의 바이트만이 며 구분되지 않기 때문에 구분하는 데 비용이 들지 않습니다. 몇 가지 테스트에 따르면 5000 바이트 정도의 포크 tr조차도이 경우에도 포크 및 파이프 비용 이 가치가 있으며 거의 ​​항상 숫자가 높아질 때입니다.

나는 달렸다 ...

time bash -c 'printf H%.0s {1..5000}' >/dev/null

...과...

time bash -c 'printf %05000s|tr \  H' >/dev/null

5 회 조각에 대한 각 (여기 과학 아무것도 - 단지 일화) 와 중괄호 확장 버전은 총 처리 시간 0.02 초 조금 넘는 평균 있지만 tr버전은 0.012 주위 초에 와서 평균 총 - 그리고 tr버전은 그것을 이길 매번. 나는 놀랍다 고 말할 수 없다- {brace expansion}유용한 대화 형 쉘 속기 기능이지만 일반적으로 모든 종류의 스크립팅과 관련하여 수행하는 것은 오히려 낭비입니다. 일반적인 형태 :

for i in {[num]..[num]}; do ...

... 생각할 때 실제로 두 개의 for 루프가 있습니다. 첫 번째는 내부 루프이며 쉘은 반복자를 생성하기 전에 반복자를 생성하기 위해 어떤 방식으로 루프를 반복해야한다는 것을 암시합니다 for. 이러한 작업은 일반적으로 다음과 같이 수행하는 것이 좋습니다.

iterator=$start
until [ "$((iterator+=interval))" -gt "$end" ]; do ...

... 반복 가능한 값을 생성하는 동안 반복을 수행 할뿐만 아니라 매우 적은 값만 저장하고 덮어 쓰므로 덮어 씁니다.

어쨌든, 앞서 언급 한 스페이스 패딩과 같이, 다음과 같이 printf임의의 숫자를 제로 패딩하는 데 사용할 수도 있습니다 .

printf %05000d

printf인수를 찾을 수 없을 때의 형식 문자열에 지정된 모든 인수에 대해 널 문자열이 사용되므로 숫자 인수의 경우 0 또는 문자열의 빈 문자열로 해석 되므로 인수없이 둘 다 수행 합니다.

이것은 문제의 명령과 비교할 때 동전 의 다른 측면 (그리고 내 의견으로는 더 효율적인 측면)입니다. printf %.0각 인수의 문자열 길이 를 지정할 때와는 달리 아무것도 얻을 수 없으므로 아무것도 아닌 것을 얻을 수 있습니다.

대량의 생성 된 바이트에 대해서는 여전히 dd다음과 같이 사용할 수 있습니다 .

printf \\0| dd bs=64k conv=sync 

... 그리고 일반 파일 ddseek=[num]인수를 사용하면 더 큰 이점을 얻을 수 있습니다. 당신이 추가하면 당신은 64K 줄 바꿈이 아닌 널 (null)을 얻을 수 있습니다 ,unblock cbs=1줄에 임의의 문자열이 주입 할 수 위의에 paste/dev/null-하지만 그 경우를, 그것은 당신에게 사용할 수있는 경우, 당신은뿐만 아니라 사용할 수 있습니다 :

yes 'output string forever'

dd어쨌든 몇 가지 예가 있습니다.

dd bs=5000 seek=1 if=/dev/null of=./H.txt

... 생성되는 (또는 자릅니다)\0NUL 크기 5000 바이트 H.txt라는 이름의 현재 디렉토리에 작성 파일을. dd오프셋을 똑바로 찾고 그 뒤에 모든 NUL을 채 웁니다.

<&1 dd bs=5000 conv=sync,noerror count=1 | tr \\0 H >./H.txt

... 이름과 크기는 같지만 H 문자로 채워진 파일을 만듭니다. 그것은을 활용 dd하면 읽기 오류의 경우에는 적어도 하나의 전체 널 블록을 작성의 spec'd 행동 noerrorsync변환이 지정됩니다 (-없이 count=가능성이 당신이 원하는 것보다 더 오래 갈 것 -) 리디렉션을 의도적으로 ddstdin의 쓰기 전용 파일 디스크립터


8

%.0sA와 인수를 변환하는 것을 의미 문자열 으로, 정밀 제로. 에 따르면 man 3 printf, 그러한 경우의 정밀도 값은

   [ ... ] the  maximum  number  of characters to be printed from a
   string for s and S conversions.

따라서 정밀도가 0이면 문자열 인수 가 전혀 인쇄되지 않습니다. 그러나,이 H인자가 있기 때문에 (어떤은 형식 지정자의 일부 임)에 따라 이후 여러 번 인쇄 얻는다 printf섹션man bash

The format is reused as necessary to consume all  of  the  argu
ments.  If the format requires more arguments than are supplied,
the extra format specifications behave as if  a  zero  value  or
null  string,  as  appropriate,  had  been supplied. 

7

이 경우 %.0s항상 앞에있는 하나의 문자 인스턴스 (이 경우 H)를 인쇄합니다. {1..5000}을 사용하면 쉘이이를 확장하여 다음과 같이됩니다.

printf 'H%.0s' 1 2 3 4 ... 5000 > H.txt

즉, printf 명령에는 이제 5000 개의 인수가 있으며 각 인수마다 하나의 H를 얻게됩니다. 이들은 순차적이거나 숫자 일 필요는 없습니다.

printf 'H%.0s' a bc fg 12 34

prints- HHHHH즉, 인수 개수,이 경우 5

위의 첫 번째 예에서 타원은 문자 그대로 삽입되지 않으며 시퀀스 또는 범위를 나타냅니다.

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