여러 파일에서 특정 문자열 뒤에 오는 모든 숫자의 평균을 반환하고 싶습니다.
10개의 파일(file1.txt,...,file10.txt)이 있습니다. 각 파일에는 다른 콘텐츠가 포함되어 있습니다.
Test1: Avg. length 24.01000, time: 0.579
Test2: Avg. length 22.02000, time: 0.879
다른 숫자로.
10개의 파일이 있다면 다음과 같을 것입니다.
파일 1.txt
Test1: Avg. length 24.01000, time: 0.679
Test2: Avg. length 22.01000, time: 0.479
파일 2.txt
Test1: Avg. length 27.01000, time: 0.279
Test2: Avg. length 24.01000, time: 0.779
…
파일 10.txt
내가 원하는 출력은 모든 파일에서 Test1과 Test2의 길이와 시간의 평균입니다.
Mean Test1: Avg. length (file1_Test1_length+...+file10_Test1_lenght)/10, time (file1_Test1_time+...+file_10_Test1_time)/10
Mean Test2: Avg. length (file1_Test2_length+...+file10_Test2_lenght)/10, time (file1_Test2_time+...+file_10_Test2_time)/10
Test1의 전체 출력을 grep하려면 다음을 실행합니다.
egrep -rh 'Test1: Avg. length.*' /home/timo/Documents
숫자만 grep하는 방법을 모르겠습니다. 나는 노력했다
egrep -rhP '(?<=length )\d+' /home/timo/Documents
그런데 오류가 발생해요
grep: conflicting matchers specified
누구든지 나를 도울 수 있다면 매우 감사하겠습니다!
답변1
다음 awk
솔루션이 작동합니다.
awk -F'[ ,:]+' '$1~/^Test[12]/{l[$1]+=$4; t[$1]+=$6; n[$1]++;}
END{if (n["Test1"]) {for (tst in l) printf("Mean %s: Avg. length %f, time: %f\n",tst,l[tst]/n[tst], t[tst]/n[tst]);} else {print "No input found"}}' file*.txt
Test1
그러면 입력 파일에서 or로 시작하는 행 Test2
과 합계 필드 4와 6(각각 "길이" 및 "시간") 을 구문 분석합니다 . 또한 데이터 카운터도 증가합니다 n
. 마지막으로 평균값(데이터가 발견된 경우) 또는 오류 메시지를 인쇄합니다.
최소한 하나의 파일이 존재한다고 확신하는 경우 이를 다음과 같이 단순화할 수 있습니다.
awk -F'[ ,:]+' '$1~/^Test[12]/{l[$1]+=$4; t[$1]+=$6; n[$1]++;}
END{for (tst in l) printf("Mean %s: Avg. length %f, time: %f\n",tst,l[tst]/n[tst], t[tst]/n[tst]);}' file*.txt
모든 파일이 별도의 하위 폴더에 있는 것으로 나타나므로 방법은 셸에 따라 다릅니다. 가장 간단한 경우에는 시도해 볼 수 있습니다.
awk -F'[ ,:]+' ' ... ' subdir*/file*.txt
답변2
GNU 사용 datamash
:
$ grep '^Test.*Avg\. length.*time:' file*.txt | tr -d ',' | LC_ALL=C datamash -W -s -g 1 mean 4,6
Test1: 25.51 0.479
Test2: 23.01 0.629
먼저 표시하는 데 사용하는 행을 추출합니다 grep
. Test
줄의 시작 부분에 있는 텍스트를 일치시킨 다음 문자열 Avg. length
과 time:
줄의 다른 부분을 일치시켜 이를 수행합니다 . 이 표현식을 수정하고 싶을 수도 있습니다(고유하게 일치하는지 모르겠습니다.오직우리가 관심 있는 행).
그런 다음 숫자 해석을 엉망으로 만들기 때문에 데이터에서 모든 쉼표를 제거했습니다. 나는 이것을 사용하여 tr
.
grep
+ 비트는 다음을 사용 tr
하여 수행 할 수도 있습니다.sed
sed '/^Test.*Avg\. length.*time:/!d; s/,//g' file*.txt
그런 다음 GNU를 사용하여 datamash
각 테스트의 평균 길이와 시간을 계산합니다. 나는 처음에 datamash
공백을 구분 기호로 사용하라고 말했습니다 -W
. + (또는 ) -s
에서 오는 대로 데이터를 정렬하여 데이터를 전역적으로 효과적으로 그룹화합니다.grep
tr
sed
그룹화는 각 행의 레이블을 그룹화 키로 -g 1
정의 하여 TestN:
수행 됩니다. 그런 다음 각 그룹에 대해 공백으로 구분된 4번째와 6번째 열의 평균을 계산합니다 mean 4,6
. 여기서 .
유틸리티에서 소수점이 점 대신 쉼표를 사용할 것으로 예상할 수 있으므로 C
(POSIX 로케일) 에 대한 로케일을 설정했습니다 .datamash
출력을 약간 장식하려면 다음 명령을 사용할 수 있습니다 awk
.
sed '/^Test.*Avg\. length.*time:/!d; s/,//g' file*.txt |
LC_ALL=C datamash -W -s -g 1 mean 4,6 |
awk '{ printf "%s Avg. length: %s time: %s\n", $1,$2,$3 }'
이는 다음과 같이 출력될 수 있습니다.
Test1: Avg. length: 25.51 time: 0.479
Test2: Avg. length: 23.01 time: 0.629