모든 것이 같은 폭을 갖도록 bash에서 정수 시퀀스를 제로 패드하는 방법은 무엇입니까?
몇 가지 가치관을 반복해야 합니다.
for i in $(seq $first $last)
do
does something here
done
위해서$first
그리고.$last
저는 그것의 길이가 고정된 길이 5로 해주세요.그래서 만약 입력이1
앞에 0을 더해서 0이 되도록 해야 합니다.00001
까지 순환합니다.99999
예를 들어, 길이는 5여야 합니다.
예:00002
,00042
,00212
,12312
등등.
어떻게 해야 할지 생각나는 거 있어요?
구체적인 경우에는 사용하는 것이 아마도 가장 쉬울 것입니다.-f
에 깃발을 내미는.seq
목록을 출력할 때 번호 형식을 지정할 수 있습니다.예:
for i in $(seq -f "%05g" 10 15)
do
echo $i
done
는 다음과 같은 출력을 생성합니다.
00010
00011
00012
00013
00014
00015
더 일반적으로 말하면,bash
가지다printf
다음과 같이 0으로 출력을 패딩할 수 있습니다.
$ i=99
$ printf "%05d\n" $i
00099
사용할 수 있습니다.-v
플래그 - 출력을 다른 변수에 저장합니다.
$ i=99
$ printf -v j "%05d" $i
$ echo $j
00099
주의:printf
에 약간 다른 형식을 지원합니다.seq
그래서 당신은 사용할 필요가 있습니다.%05d
대신에%05g
.
더 쉬워도 그냥 할 수 있습니다.
for i in {00001..99999}; do
echo $i
done
시퀀스의 끝에 최대 패딩 길이가 있는 경우(예: 5자리 숫자를 원하는 경우), 명령어는seq 1 10000
), 사용할 수 있는 것보다 많습니다.-w
seq 플래그 - 패딩 자체를 추가합니다.
seq -w 1 10
을 생산할 것입니다.
01
02
03
04
05
06
07
08
09
10
예를 들어 "%05d"와 함께 printf를 사용합니다.
printf "%05d" 1
매우 단순한 사용printf
[jaypal:~/Temp] printf "%05d\n" 1
00001
[jaypal:~/Temp] printf "%05d\n" 2
00002
다음과 같이 awk를 사용합니다.
awk -v start=1 -v end=10 'BEGIN{for (i=start; i<=end; i++) printf("%05d\n", i)}'
출력:
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
업데이트:
순수 bash 대체 방법으로 동일한 출력을 얻기 위해 다음을 수행할 수 있습니다.
for i in {1..10}
do
printf "%05d\n" $i
done
이렇게 하면 외부 프로그램 사용을 피할 수 있습니다.seq
일부 *nix 버전에서는 사용할 수 없습니다.
필요한 숫자보다 더 많은 숫자(0)로 출력을 입력한 다음 테일을 사용하여 원하는 숫자만 사용합니다.마지막 다섯 자리를 얻으려면 꼬리에 '6'을 사용해야 합니다 :)
for i in $(seq 1 10)
do
RESULT=$(echo 00000$i | tail -c 6)
echo $RESULT
done
N자리를 원하는 경우 10^N을 추가하고 첫 번째 자리를 삭제합니다.
for (( num=100; num<=105; num++ ))
do
echo ${num:1:3}
done
출력:
01
02
03
04
05
다른 방법:
zeroos="000"
echo
for num in {99..105};do
echo ${zeroos:${#num}:${#zeroos}}${num}
done
따라서 임의의 숫자를 변환하는 간단한 함수는 다음과 같습니다.
function leading_zero(){
local num=$1
local zeroos=00000
echo ${zeroos:${#num}:${#zeroos}}${num}
}
외부 프로세스 포킹을 사용하지 않는 한 가지 방법은 문자열 조작이며, 일반적인 경우 다음과 같습니다.
#start value
CNT=1
for [whatever iterative loop, seq, cat, find...];do
# number of 0s is at least the amount of decimals needed, simple concatenation
TEMP="000000$CNT"
# for example 6 digits zero padded, get the last 6 character of the string
echo ${TEMP:(-6)}
# increment, if the for loop doesn't provide the number directly
TEMP=$(( TEMP + 1 ))
done
이것은 WSL에서도 꽤 잘 작동하는데, 여기서 포킹은 정말로 무거운 작업입니다.1,10000개의 파일 목록을 가지고 있었습니다.printf "%06d" $NUM
1분 이상 걸렸고, 상기 솔루션은 약 1초 만에 실행되었습니다.
이 기능은 다음과 같습니다.
for i in {0..9}{0..9}{0..9}{0..9}
do
echo "$i"
done
고정 길이를 달성하기 위해 숫자를 0으로 채우는 경우에는 가장 가까운 10 eg의 배수를 추가하면 됩니다.두 자리의 경우 10^2를 추가한 다음 출력을 표시하기 전에 첫 번째 1을 제거합니다.
이 솔루션은 for 루프를 사용하여 임의의 길이의 단일 숫자 또는 전체 숫자 시퀀스를 패딩/포맷할 수 있습니다.
# Padding 0s zeros:
# Pure bash without externals eg. awk, sed, seq, head, tail etc.
# works with echo, no need for printf
pad=100000 ;# 5 digit fixed
for i in {0..99999}; do ((j=pad+i))
echo ${j#?}
done
Mac OS X 10.6.8, Bash 버전 3.2.48에서 테스트됨
TL;DR
$ seq 1 10 | awk '{printf("%05d\n", $1)}'
입력(패턴 1).느림):
$ seq 1 10 | xargs -n 1 printf "%05d\n"
입력(패턴 2).빠름):
$ seq 1 10 | awk '{printf("%05d\n", $1)}'
출력(각 사례에서 동일한 결과):
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
설명.
저는 위의 패턴을 제안하고 싶습니다.이러한 구현을 명령어로 사용하여 쉽게 다시 사용할 수 있습니다.이러한 명령에서 주의해야 할 것은 변환된 후의 숫자의 길이입니다.(숫자를 바꾸는 것처럼)%05d
안으로%09d
할 수 .) 또한 다음과 같은 다른 솔루션에도 적용할 수 있습니다.예제는 내 환경에 너무 의존적이어서 출력이 다를 수 있지만 유용성은 쉽게 알 수 있다고 생각합니다.
$ wc -l * | awk '{printf("%05d\n", $1)}'
00007
00001
00001
00001
00013
00017
00001
00001
00001
00043
그리고 이런 식으로:
$ wc -l * | awk '{printf("%05d\n", $1)}' | sort | uniq
00001
00007
00013
00017
00043
게다가, 당신이 이런 식으로 글을 쓴다면, 우리는 또한 비동기식으로 명령을 실행할 수 있습니다. (좋은 기사입니다.
고지 사항:저는 이것에 대해 확신할 수 없고 *nix 전문가도 아닙니다.
성능 테스트:
매우 느림:
$ time seq 1 1000 | xargs -n 1 printf "%09d\n" > test
seq 1 1000 0.00s user 0.00s system 48% cpu 0.008 total
xargs -n 1 printf "%09d\n" > test 1.14s user 2.17s system 84% cpu 3.929 total
비교적 빠른 속도:
for i in {1..1000}
do
printf "%09d\n" $i
done
$ time sh k.sh > test
sh k.sh > test 0.01s user 0.01s system 74% cpu 0.021 total
for i in {1..1000000}
do
printf "%09d\n" $i
done
$ time sh k.sh > test
sh k.sh > test 7.10s user 1.52s system 99% cpu 8.669 total
빠른 속도:
$ time seq 1 1000 | awk '{printf("%09d\n", $1)}' > test
seq 1 1000 0.00s user 0.00s system 47% cpu 0.008 total
awk '{printf("%09d\n", $1)}' > test 0.00s user 0.00s system 52% cpu 0.009 total
$ time seq 1 1000000 | awk '{printf("%09d\n", $1)}' > test
seq 1 1000000 0.27s user 0.00s system 28% cpu 0.927 total
awk '{printf("%09d\n", $1)}' > test 0.92s user 0.01s system 99% cpu 0.937 total
고성능 솔루션을 구현해야 하는 경우 셸 스크립트를 사용하지 않고 다른 기술이 필요할 수 있습니다.
조합seq -w
질문에 대한 @precipee의 의견으로 답변하면 다음을 수행할 수 있습니다.
seq -w 1 1000 | while read -r i; do
echo $i
done
@tripleee linked 기사에서 설명한 것처럼, 이것은 전체 시퀀스를 한 번에 메모리에 로드하는 대신 파이프에서 한 번에 단일 숫자를 읽습니다.
버전이나 루프 버전에 비해 의미 {0000..1000}
판본
루프를 피할 수 있습니까?
여러 인수를 허용하는 명령을 실행하기 위해 이 작업을 수행하는 경우 루프 작업보다 여러 인수를 사용하여 명령을 직접 실행하고 확장을 지원하는 것이 더 빠를 수 있습니다.
예를 들어 시스템에서 다음 루프를 실행하는 데 7초가 걸립니다.
for i in {0001..9001}; do; touch $i; done
그러나 다음은 거의 즉시 실행됩니다.
touch {0001..9001}
1.) 1부터 1000까지의 일련의 숫자 'seq'를 만들고 너비 '-w'를 고정합니다(이 경우 너비는 끝 숫자의 길이로 결정됩니다. 이 경우 1000에 대한 4자리 숫자).
2.) 또한 'sed -n'을 사용하여 원하는 숫자를 선택합니다(이 경우 1-100번을 선택합니다).
3.) 각 숫자를 '표기'합니다.숫자는 변수 'i'에 저장되며, '$'를 사용하여 액세스합니다.
찬성: 이 코드는 꽤 깨끗합니다.
단점: 'seq'가 모든 Linux 시스템에 기본적인 것은 아닙니다(제가 알기로는).
for i in `seq -w 1 1000 | sed -n '1,100p'`;
do
echo $i;
done
필없니다가 필요 없습니다.awk
- 위해면니 --아을것그▁that.seq
또는jot
단독으로 충분합니다.
% seq -f '%05.f' 6 # bsd-seq
00001
00002
00003
00004
00005
00006
% gseq -f '%05.f' 6 # gnu-seq
00001
00002
00003
00004
00005
00006
% jot -w '%05.f' 6
00001
00002
00003
00004
00005
00006
당신이 큰 영토로 들어가지 않는 한:
% gawk -Mbe '
function __(_,___) {
return +_<+___?___:_
}
BEGIN {
_+=_^=_<_
____="%0*.f\n"
} {
___=__($--_, !+$++_)
_____=__(++_+--_, length(______=+$NF))
do {
printf(____,_____,___)
} while (___++<______)
}' <<< '999999999999999999996 1000000000000000000003'
0999999999999999999996
0999999999999999999997
0999999999999999999998
0999999999999999999999
1000000000000000000000
1000000000000000000001
1000000000000000000002
1000000000000000000003
——————————————————————————————————————————————————
만약 당신이 엄청난 범위의 숫자를 출력해야 한다면, 이 접근법은 조금 더 빠를 수도 있습니다.
단위로 , 쪽-0-0-0-0-0-9-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0
0.049s
*caveat : 모든 입력 범위를 커버할 여유가 없었습니다 :: 10의 거듭제곱을 수용하는 개념 증명일 뿐입니다.
——————————————————————————————————————————————————
( time ( LC_ALL=C mawk2 '
function jot(____,_______,_____,_,__,___,______) {
if(____==(____^!____)) {
return +____<+_______\
? sprintf("%0*.f",_______,____)\
: +____
}
_______= (_______-=____=length(____)-\
(_=!(_<_)))<+_ \
? "" \
: sprintf("%0*.f",_______,!_)
__=_= (!(__=_+=_+_))(__=(-+--_)+(__+=_)^++_)\
(__+=_=(((_--^_--+_++)^++_-_^!_)/_))(__+_)
_____= "."
gsub(_____,"\\&&",__)
____—-
do {
gsub(_____,__,_)
_____=_____"."
} while(—____)
gsub(_____,(_______)"&\n",_)
sub("^[^\n]+[\n]","",_)
sub(".$",""~"",_______)
return \
(_)(_______)\
sprintf("%0*.f",length(_____),__<__)
} { print jot($1,$2) }' <<< '10000000 9'
) | pvE9 ) |xxh128sum |ggXy3 | lgp3
sleep 2
( time ( LC_ALL=C jot 1000000 |
LC_ALL=C mawk2 '{ printf("%09.f\n", $1) }'
) | pvE9 ) |xxh128sum |ggXy3 | lgp3
out9: 9.54MiB 0:00:00 [ 275MiB/s] [ 275MiB/s] [<=> ]
( LC_ALL=C mawk2 <<< '1000000 9'; )
0.04s user 0.01s system 93% cpu 0.049 total
e0491043bdb4c8bc16769072f3b71f98 stdin
out9: 9.54MiB 0:00:00 [36.5MiB/s] [36.5MiB/s] [ <=> ]
( LC_ALL=C jot 1000000 | LC_ALL=C mawk2 '{printf("%09.f\n", $1)}'; )
0.43s user 0.01s system 158% cpu 0.275 total
e0491043bdb4c8bc16769072f3b71f98 stdin
천만 번을 할 때쯤이면 시차가 눈에 띕니다.
out9: 95.4MiB 0:00:00 [ 216MiB/s] [ 216MiB/s] [<=> ]
( LC_ALL=C mawk2 <<< '10000000 9'; )
0.38s user 0.06s system 95% cpu 0.458 total
be3ed6c8e9ee947e5ba4ce51af753663 stdin
out9: 95.4MiB 0:00:02 [36.3MiB/s] [36.3MiB/s] [ <=> ]
( LC_ALL=C jot 10000000 | LC_ALL=C mawk2 '{printf("%09.f\n", $1)}'; )
4.30s user 0.04s system 164% cpu 2.638 total
be3ed6c8e9ee947e5ba4ce51af753663 stdin
out9: 95.4MiB 0:00:02 [35.2MiB/s] [35.2MiB/s] [ <=> ]
( LC_ALL=C python3 -c '__=1; ___=10**7;
[ print("{0:09d}".format(_)) for _ in range(__,___+__) ]'
) | pvE9 ) | xxh128sum |ggXy3 | lgp3 ; )
2.68s user 0.04s system 99% cpu 2.725 total
be3ed6c8e9ee947e5ba4ce51af753663 stdin
언급URL : https://stackoverflow.com/questions/8789729/how-to-zero-pad-a-sequence-of-integers-in-bash-so-that-all-have-the-same-width
'source' 카테고리의 다른 글
Bash 셸 스크립트에 입력 인수가 있는지 확인합니다. (0) | 2023.05.22 |
---|---|
Xcode 'Build and Archive' 메뉴 항목 사용 안 함 (0) | 2023.05.22 |
SQL Azure 프로파일링 (0) | 2023.05.22 |
Xcode에서 모든 메서드를 축소하는 방법은 무엇입니까? (0) | 2023.05.22 |
'var' 매개 변수는 더 이상 사용되지 않으며 Swift 3에서 제거됩니다. (0) | 2023.05.22 |