printf 명령을 사용하여 문자를 N 번 쓰세요

printf 명령을 사용하여 문자를 N 번 쓰세요

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

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

예를 들어 여러 번 H반복 하고 싶습니다 . 5000여기서는 무엇을 의미하나요 %.0s?

답변1

이 명령은 셸에 따라 5000개의 인수를 생성하고 이를 printf셸에 전달한 다음 무시합니다. 꽤 빠르고 관련성이 있어 보일 수도 있지만, 쉘은 여전히 ​​모든 문자열을 args로 생성해야 합니다.(그리고 정의)등.

쉘의 첫 번째 반복이 5000에 도달할 때까지 결과 H를 인쇄할 수 없는 것 외에도 이 명령은 숫자 문자열 인수를 저장하고 구분하기 위해 메모리를 소비합니다.printf 추가하다Hs. 당신이 할 수 있는 대로:

printf %05000s|tr \  H

...5000개의 공백이 포함된 문자열을 생성합니다. 최소한 각 공백은 일반적으로 1바이트에 불과하며 구분되지 않으므로 구분 비용이 필요하지 않습니다. 일부 테스트에 따르면 이 경우에도 필요한 분기 및 배관 비용은 tr5000바이트에 불과하더라도 그만한 가치가 있으며 숫자가 더 높아질수록 거의 항상 그렇습니다.

나는 도망 갔다...

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 ...

...잘 생각해 보세요. 정말 그렇네요. forLoop - 첫 번째는 내부적이며, 모든 반복자를 저장하고 루프에 대해 다시 반복하기 전에 쉘이 이러한 반복자를 생성하기 위해 어떻게든 반복해야 함을 의미합니다 for. 일반적으로 다음과 같은 작업을 수행하는 것이 더 좋습니다.

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

...매우 적은 값만 저장하고 반복 가능 항목을 생성할 때 반복하고 사용할 때 덮어쓰기 때문입니다.

어쨌든 앞서 언급한 공백 채우기와 마찬가지로 원하는 수 printf의 숫자를 0으로 채울 수도 있습니다. 예를 들면 다음과 같습니다.

printf %05000d

printf형식 문자열에 지정된 각 인수에 대해 인수를 찾을 수 없으면 빈 문자열이 사용되기 때문에 인수 없이 두 작업을 모두 수행합니다. 이는 숫자 인수에 대해 0 또는 문자로 해석됩니다. 문자열의 빈 문자열입니다.

이건 또 다른 거야(그리고 - 제 생각에는 - 더 효율적입니다)이것은 질문의 명령과 비교하면 동전의 한 면입니다. printf %.0각 인수 길이에 대해 문자열과 같은 것에서 무엇이든 얻을 수 있으므로 무에서 무언가를 얻는 것도 가능합니다.

대량의 바이트가 생성된 경우 다음과 같은 더 빠른 방법을 사용할 수 있습니다 dd.

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

...그리고 일반 파일 dd의 매개변수를 사용하면 seek=[num]더 큰 이점을 얻을 수 있습니다. 위에 내용을 추가하면 ,unblock cbs=1null 대신 64k 줄 바꿈을 얻을 수 있으며 거기에서 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시 읽기 오류가 발생할 경우 최소한 완전한 빈 블록을 작성하는 표준 동작을 활용합니다.noerrorsync(그렇지 않으면 count=원하는 것보다 오래 지속될 수도 있습니다)dd, 의도적으로 stdin에서 쓰기 전용 파일 설명자를 리디렉션합니다.

답변2

%.0s매개변수를 다음으로 변환, 하나 있어요정확한0입니다. 에 따르면 man 3 printf, 이 경우의 정밀도 값은 다음과 같이 주어진다.

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

따라서 정밀도가 0일 때,문자열 매개변수인쇄가 전혀 되지 않습니다. 그러나 (형식 지정자의 일부인) 은 H인수만큼 인쇄됩니다.printfman 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. 

답변3

이 경우 %.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

인쇄 HHHHH- 이는 매개변수의 수이며, 이 경우에는 5입니다.

위의 첫 번째 예에서 줄임표는 문자 그대로 삽입된 것이 아니라 순서나 범위를 나타내는 데 사용되었습니다.

관련 정보