중복을 제거하기 위해 행에 숫자 접미사를 추가하는 방법은 무엇입니까?
의사코드:
if currLine.startsWith("tag:")
x = numFutureLinesMatching(currLine)
if (x > 0)
currLine = currLine + ${x:01}
입력 파일
tag:20230901-FAT
val:1034
tag:20230901-FAT
val:1500
tag:20230901-LAX
val:8934
tag:20230901-SMF
val:2954
tag:20230901-LAX
val:1000
tag:20230901-FAT
val:1500
원하는 출력
tag:20230901-FAT-02
val:1034
tag:20230901-FAT-01
val:1500
tag:20230901-LAX-01
val:8934
tag:20230901-SMF
val:2954
tag:20230901-LAX
val:1000
tag:20230901-FAT
val:1500
노트:
- 최종 사본은 변경되지 않은 상태로 유지되어야 합니다.
- 초기 중복에는 고유한 접미사가 붙을 수 있으므로 카운트다운을 선택했습니다.
- awk는 좋은 선택인 것처럼 보이지만 일반적인 스크립팅 언어라면 모두 가능합니다.
답변1
awk
모든 배열 인덱스를 사용할 수 있습니다. 심지어 전체 레코드("행")도 사용할 수 있습니다.
정규식 일치를 만들고 tag:
카운터를 시작하지만 첫 번째 일치 때문에 하나를 수정합니다.
awk '$0 ~ /^tag:/ { n[$0]++?$0=sprintf("%s-%02d",$0,n[$0]-1):1 } 1'
카운트다운으로 만들려면 tac
두 번 사용하세요.
tac infile |
awk '$0 ~ /^tag:/ { n[$0]++?$0=sprintf("%s-%02d",$0,n[$0]-1):1 } 1' |
tac
답변2
요청한 대로 정확하게 시작해 보겠습니다.
awk '
NR==FNR{
if (/^tag:/) {
a[$1]++
}
next
}
{
c=--a[$1]
if (c>0) {
printf "%s-%.2d\n", $1, c
} else {
print
}
}
' file file
설명:
awk '
# first block for first file
NR==FNR{ # first file
if (/^tag:/) # if the line starts with ^tag:
a[$1]++ # increment array a with key as column 1
next # stop processing this line
}
# 2th block for second file
{
c=--a[$1] # c = decrement array a with key as column 1
if (c>0) { # ... pretty simple, no ?
printf "%s-%.2d\n", $1, c # %s = string %.2d integer, zero pading
} else {
print # else, print current line
}
}
' file file
산출
tag:20230901-FAT-02
val:1034
tag:20230901-FAT-01
val:1500
tag:20230901-LAX-01
val:8934
tag:20230901-SMF
val:2954
tag:20230901-LAX
val:1000
tag:20230901-FAT
val:1500
답변3
그리고진주:
#!/usr/bin/perl
use strict; use warnings;
use feature qw/say/;
my (%h, $c);
while (<>) {
chomp;
if (/^tag:/) {
$c = sprintf "%.2d", ++$h{$_};
if ($c>1) {
say $_ . "-" . $c;
} else {
say;
}
} else {
say $_;
}
}
용법:
./script file
산출:
tag:20230901-FAT
val:1034
tag:20230901-FAT-02
val:1500
tag:20230901-LAX
val:8934
tag:20230901-SMF
val:2954
tag:20230901-LAX-02
val:1000
tag:20230901-FAT-03
val:1500
답변4
사용행복하다(이전 Perl_6)
~$ raku -ne 'BEGIN my %hash; put /^tag\:/ && %hash{$_}++ ?? $_ ~ sprintf("-%02d", %hash{$_}-1) !! $_;' file
awk
위는 @EdMorton이 댓글에 게시한 우수한 답변의 Raku 버전입니다.
-ne
먼저 자동 인쇄가 아닌 한 줄씩 플래그를 사용하여 명령줄에서 Raku를 호출합니다 . BEGIN
명령문을 통한 입력 시 명령문을 실행합니다 %hash
. put
행이 /^tag:/
다음으로 시작하는 경우 tag:
행을 추가 %hash
하고 ++
해당 값을 늘립니다.
이 &&
조건이 라쿠의 “시험 ??
진짜 !!
잘못된" 삼항 연산자. True인 경우 행에서 1을 뺀 값이 추가된 $_
행이 출력됩니다 (디코딩된 값 사용 ). False인 경우 행은 변경되지 않고 출력됩니다 .put
%hash{$_}
put
입력 예:
tag:20230901-FAT
val:1034
tag:20230901-FAT
val:1500
tag:20230901-LAX
val:8934
tag:20230901-SMF
val:2954
tag:20230901-LAX
val:1000
tag:20230901-FAT
val:1500
예제 출력:
tag:20230901-FAT
val:1034
tag:20230901-FAT-01
val:1500
tag:20230901-LAX
val:8934
tag:20230901-SMF
val:2954
tag:20230901-LAX-01
val:1000
tag:20230901-FAT-02
val:1500
위의 내용은 계산 접미사를 구현하여 가장 오래된 tag:
행을 변경하지 않고 유지합니다. 마지막 몇 줄을 변경하지 않고 그대로 두는 카운트다운 접미사를 구현하려면 tag:
@FelixJN tac
의 허용 답변에 지시된 대로 두 번 사용하세요. tail -r
대신 다음 을 사용하여 MacOS에서 구현된 답변은 다음과 같습니다 tac
.
~$ tail -r Steve_suffix.txt | raku -ne 'BEGIN my %hash; put /^tag:/ && %hash{$_}++ ?? $_ ~ sprintf("-%02d", %hash{$_}-1) !! $_;' | tail -r
tag:20230901-FAT-02
val:1034
tag:20230901-FAT-01
val:1500
tag:20230901-LAX-01
val:8934
tag:20230901-SMF
val:2954
tag:20230901-LAX
val:1000
tag:20230901-FAT
val:1500
https://unix.stackexchange.com/a/114043
https://docs.raku.org/언어/operators#infix_??_!!
https://raku.org