%EC%9D%84%20%EC%B6%94%EC%B6%9C%ED%95%98%EB%8A%94%20%EB%B0%A9%EB%B2%95%EC%9D%80%20%EB%AC%B4%EC%97%87%EC%9E%85%EB%8B%88%EA%B9%8C%3F.png)
Bash 스크립트를 사용하여 각 행의 최대값(열 헤더 값 또는 첫 번째 행의 동일한 열 값)을 사용하여 열 이름을 추출하려고 합니다. 다음 명령을 사용하여 CSV 파일의 각 행에서 최대값을 추출하고 있지만 최대값과 함께 열 이름을 인쇄하는 방법을 찾을 수 없습니다.
awk -F ',' '{max=$'$col1';for (i=1;i<=NF;i++) {if ($i > max){max=$i}};print " max: " max}' "$INPUT_PATH/tmp.csv" >>$INPUT_PATH/max1.csv
예:
샘플 CSV 데이터:
col1,col2,col3,col4
1,5,2,6
4,0,1,2
1,2,0,0
0,0,7,0
원하는 출력:
col4 6 2
col1 4 1
col2 2 2
col3 7 3
위 명령에 이 작업을 수행할 수 있는 방법이 있습니까, 아니면 CSV 파일에서 필요한 정보를 추출하는 더 좋은 방법이 있습니까?
답변1
밀러 사용(https://github.com/johnkerl/miller) 그리고 실행
mlr --c2n merge-fields -a max -r "^[a-z]" -o value -k then put '
for (key, value in $*) {
if (value == $value_max && key != "value_max") {
$fieldName=key;
}
}' then cut -f fieldName,value_max then reorder -f fieldName,value_max input.csv
당신은 할 것
col4 6
col1 4
col2 2
col3 7
답변2
사용 tr
및datamash
:
tr , '\t' < file.csv | datamash -H max 1-4 | datamash transpose
산출:
max(col1) 4
max(col2) 5
max(col3) 7
max(col4) 6
노트:
선행이 필요하지 않은 경우
sed
일부를 사용하여 출력을 정리할 수 있습니다.max()
열의 개수를 특별히 알 수는 없지만 확실히 큰 개수보다 적은 경우 로 바꾸고
1-4
필요1-1000
에 따라 0을 추가합니다.정확한 개수를 얻으려면
4
,$(head -1 file.csv | tr , ' ' | wc -w)
또는 (을 사용하여) 로 바꾸십시오.POSIX껍데기)$(read x < file.csv; echo ${x##*l};)
.정리와 정확한 계산을 통해 결과적으로 보기 흉한 코드는 다음과 같습니다.
tr , '\t' < file.csv | datamash -H max 1-$(read x < file.csv; echo ${x##*l};) | datamash transpose | sed 's/.*(\|)//g'
산출:
col1 4 col2 5 col3 7 col4 6
답변3
mx=0
레코드의 모든 필드가 음수이면 초기 값 설정 솔루션이 실패합니다. 안전하도록 설정 $1
하면 필드가 @Peter.O처럼 반복될 수 있습니다.
재미삼아 카운터와 루프를 생성하는 대신 배열 인덱스를 awk
반복하는 약간의 변형이 있습니다.head
awk -F',' '
NR==1{split($0,head,FS); next}
{x=1; for (h in head) if ($h>$x) x=h;print head[x], $x }
' file
산출
col4 6
col1 4
col2 2
col3 7
답변4
CSV의 문제점은 일반 쉘 도구로는 잘 구문 분석되지 않는다는 것입니다. 그들은 단지 그것을 잘 하지 못할 뿐입니다. 그것할 수 있는사소한 경우에는 할 수 있지만 실제로는 스크립팅 언어가 작업 도구입니다.
나는 perl
좀 더 개인적으로 생각합니다.
#!/usr/bin/env perl
use strict;
use warnings;
use Text::CSV;
my $csv = Text::CSV->new();
open ( my $input, "<", "your_file.csv" ) or die $!;
$csv->column_names( $csv->getline( $input ) );
while ( my $row = $csv->getline_hr( $input ) ) {
my ( $highest, @rest ) = sort { $row->{$b} <=> $row->{$a} } keys %$row;
print join( "\t", $highest, $row->{$highest} ), "\n";
}
입력으로 사용되는 경우:
first,second,third,fourth
1,3,4,5,
5,4,3,2,
1,1,4,1,
다음을 인쇄합니다:
fourth 5
first 5
third 4