수정하고 싶은 파일이 있습니다. 동일한 문제가 있는 파일이 100개 있습니다. 입력 파일은 다음과 같습니다
sample1 100A total 1 1000
sample2 100A total 1 5584
sample3 100A total 1 8125
sample4 100A total 1 59
sample1 . year 1 1000
sample1 . week1 20 1001
sample1 . week2 50 1001
sample2 . year 1 5584
sample2 . week1 20 5585
sample2 . week2 100 5585
sample3 . year 1 8125
sample3 . week1 55 8126
sample3 . week2 100 8126
sample4 . year 1 59
sample4 . week1 10 59
sample4 . week2 8 59
위 파일에서 세 번째 열의 "합계"는 조회 테이블이며 최대값은 아래 각 샘플의 행을 초과해서는 안 됩니다.
예를 들어 "sample1"의 최대값은 1000이지만, 세 번째 열의 "week1"과 "week2"의 최대값은 "1001"입니다. 나는 이것이 "week1 및 week2"의 몇 행에서만 발생하며 항상 최대값보다 1만 크다는 것을 발견했습니다. "week1" 및 "week2" 행의 출력은 최대값 "1000"으로 업데이트되어야 합니다. 아래 출력 예
sample1 100A total 1 1000
sample2 100A total 1 5584
sample3 100A total 1 8125
sample4 100A total 1 59
sample1 . year 1 1000
sample1 . week1 20 1000
sample1 . week2 50 1000
sample2 . year 1 5584
sample2 . week1 20 5584
sample2 . week2 100 5584
sample3 . year 1 8125
sample3 . week1 55 8125
sample3 . week2 100 8125
sample4 . year 1 59
sample4 . week1 10 59
sample4 . week2 8 59
어떻게 진행해야 하는지 지침을 제공해 주세요. 저는 배우고 싶은 초보 프로그래머입니다. 당신의 도움을 주셔서 감사합니다
답변1
사용행복하다(이전 Perl_6)
~$ raku -e 'my @a = slurp.split("\n\n", 2); print @a[0] ~ "\n\n";
my %h; for @a.[0].lines() { \%h.push: .words.[0,4] };
for @a[1].lines {
S/^ (\S+)(.* \s)(\S+) $/{"$0$1"}{ %h{$0} < $2 ?? "%h{$0}" !! "$2" }/.put };' file.txt
Raku는 Perl 계열의 프로그래밍 언어이므로 구문은 틀림없이 "Perl과 유사"합니다. 위에서는 slurp
파일을 한꺼번에 메모리에 넣고 2
첫 번째 단락 이후에 파일을 여러 부분으로 나눕니다. 이 데이터는 @a
배열 에 저장됩니다 . 기준값( )이 포함된 첫 번째 부분은 @a[0]
즉시 편집됩니다 print
.
%h
그런 다음 해시 값을 선언합니다. ...() 를 @a[0]
사용하여 for
상단 요약 단락을 반복 합니다 lines
. 여기서 각 행은 공백으로 구분된 행으로 분할 words
되고 첫 번째/다섯 번째 열은 .[0,4]
참조 키/값 쌍으로 push
해시에 추가됩니다 .%h
파일의 나머지 부분( )은 @a[1]
다음을 사용하여 반복됩니다. 이는 블록의 각 줄을 분석/수정할 수 있음을 의미합니다. 수정된 문자열을 반환하기 위해 Raku의 비파괴 대체 관용구를 사용하여 입력을 첫 번째(키) 열, 중간 열 및 마지막(값) 열로 분할합니다.for
lines
S///
$0
$1
$2
교체에서는 그대로 {"$0$1"}
인쇄합니다. 그러나 마지막 열의 경우 Raku의 삼항 연산자를 사용하여 중괄호 안에 코드를 실행할 수 있습니다.시험 ??
진짜 !!
잘못된이보다 작으면 %h{$0}
( key
관련 항목)을 반환하고, 그렇지 않으면 원래 값()을 반환합니다.value
$2
$2
입력 예:
sample1 100A total 1 1000
sample2 100A total 1 5584
sample3 100A total 1 8125
sample4 100A total 1 59
sample1 . year 1 1000
sample1 . week1 20 1001
sample1 . week2 50 1001
sample2 . year 1 5584
sample2 . week1 20 5585
sample2 . week2 100 5585
sample3 . year 1 8125
sample3 . week1 55 8126
sample3 . week2 100 8126
sample4 . year 1 59
sample4 . week1 10 59
sample4 . week2 8 59
예제 출력:
sample1 100A total 1 1000
sample2 100A total 1 5584
sample3 100A total 1 8125
sample4 100A total 1 59
sample1 . year 1 1000
sample1 . week1 20 1000
sample1 . week2 50 1000
sample2 . year 1 5584
sample2 . week1 20 5584
sample2 . week2 100 5584
sample3 . year 1 8125
sample3 . week1 55 8125
sample3 . week2 100 8125
sample4 . year 1 59
sample4 . week1 10 59
sample4 . week2 8 59
마지막으로 중간 데이터 구조를 살펴보는 것이 도움이 되는 경우가 많으므로 %h
해시는 다음과 같습니다(used .say for %h.sort;
).
sample1 => 1000
sample2 => 5584
sample3 => 8125
sample4 => 59
https://docs.raku.org/syntax/S%2F%2F%2F%20Non-destructive%20replacement
https://docs.raku.org/언어/operators#infix_??_!!
https://docs.raku.org/언어/regexes
https://raku.org
답변2
간단한 Awk 문:
awk -v OFS='\t' '$3 == "total" {maxval[$1] = $5} $1 in maxval && $5 > maxval[$1] {$5 = maxval[$1]} {print}' input.txt
몇 가지 줄 바꿈을 추가했습니다.
awk -v OFS='\t' '
$3 == "total" {
maxval[$1] = $5
}
$1 in maxval && $5 > maxval[$1] {
$5 = maxval[$1]
}
{print}' input.txt
설명하다:
첫째, 입력 파일의 변수 간격을 기반으로 원본 텍스트에서는 탭으로 구분된 텍스트라고 가정합니다.
기본적으로 Awk는 인접한 탭이나 공백 수에 따라 별도의 필드로 구문 분석합니다. 이 파일에는 괜찮습니다.
그러나 우리는 출력이 깔끔하게 정렬되기를 원하며 기본적으로 일부 필드 값을 변경하면 Awk는 해당 줄의 모든 필드 구분 기호를 단일 공백으로 변환합니다. 따라서 출력 필드 구분 기호(OFS)를 탭과 동일하게 설정하고 -v
변수를 설정하는 플래그를 사용합니다.
세 번째 필드가 "total" 문자열인 행의 경우 최대값을 연관 배열(가장 익숙한 프로그래밍 언어에 따라 "해시"라고도 함)에 저장합니다.
행의 첫 번째 필드가 연관 배열에 존재하고 다섯 번째 필드가더 큰해당 키의 최대값으로 배열에 저장된 값보다 현재 행의 다섯 번째 필드를 변경합니다.
그런 다음 수정 여부에 관계없이 현재 줄을 인쇄합니다.
제공된 입력에 대한 출력:
sample1 100A total 1 1000
sample2 100A total 1 5584
sample3 100A total 1 8125
sample4 100A total 1 59
sample1 . year 1 1000
sample1 . week1 20 1000
sample1 . week2 50 1000
sample2 . year 1 5584
sample2 . week1 20 5584
sample2 . week2 100 5584
sample3 . year 1 8125
sample3 . week1 55 8125
sample3 . week2 100 8125
sample4 . year 1 59
sample4 . week1 10 59
sample4 . week2 8 59