다음과 같은 형식의 큰 .csv(쉼표로 구분, 90,000개 이상의 행)가 있습니다.
x 좌표,m1,m2,m3 9. 맞다, 틀리다, 틀리다 -1, 맞다, 틀리다, 틀리다 0, 맞다, 틀리다, 틀리다
마지막 필드를 작성할 수 있도록 끝에 AMT 헤더가 있는 추가 열을 추가할 수 있었습니다.
소스_파일="/test/Orders_ALL.csv" Output_File="/test/Orders_ALL_MODIFIED.csv" awk -vd="BMT" -F"," 'BEGIN { OFS = "," } {$5=d;print}'"$Source_File">"$Output_File"
위 결과 후 출력:
x 좌표,m1,m2,m3,BMT 9. 옳고 그름, 그름, 기초의학이론 -1, 맞다, 틀리다, 틀리다, BMT 0, 맞다, 틀리다, 틀리다, 기본 MT
내가 달성하고 싶은 것은 두 번째 행부터 시작하는 첫 번째 열 값을 읽는 것입니다. 이 값이 0보다 작으면 "BEHIND"라는 단어를 쓰고 0인 경우 더 큰 값이면 "MID"라는 단어를 인쇄합니다. 0보다 크면 "THROUGH"라는 단어를 인쇄합니다.
원하는 결과는 다음과 같습니다.
x 좌표,m1,m2,m3,BMT 9. 참, 거짓, 거짓, 합격 -1, 맞다, 틀리다, 틀리다, 뒤처지다 0. 참, 거짓, 거짓, 보통
답변1
$ awk 'BEGIN { OFS=FS="," } $1<0 { t="BEHIND" } $1==0 { t="MID" } $1>0 { t="THROUGH" } NR==1 { t="BMT" } { print $0, t }' file.csv
xcoord,m1,m2,m3,BMT
9,TRUE,FALSE,FALSE,THROUGH
-1,TRUE,FALSE,FALSE,BEHIND
0,TRUE,FALSE,FALSE,MID
코드는 입력 및 출력 필드 구분 기호를 쉼표로 설정하는 것으로 시작됩니다. 그런 다음 첫 번째 열의 값에 따라 변수를 t
올바른 값으로 설정합니다. 입력의 첫 번째 줄을 보면 (이전에 설정된 값) t
로 설정되어 있습니다 . BMT
그런 다음 현재 줄을 t
끝에 새 필드로 인쇄합니다.
형식이 약간 더 좋습니다.
awk 'BEGIN { OFS = FS = "," }
$1 < 0 { t = "BEHIND" }
$1 == 0 { t = "MID" }
$1 > 0 { t = "THROUGH" }
NR == 1 { t = "BMT" }
{ print $0, t }' file.csv
펄 사용:
$ perl -lane 'BEGIN { @t=(qw(BEHIND MID THROUGH)) } printf("%s,%s\n", $_, $. == 1 ? "BMT" : $t[1+($F[-1] <=> 0)])' file.csv
xcoord,m1,m2,m3,BMT
9,TRUE,FALSE,FALSE,THROUGH
-1,TRUE,FALSE,FALSE,BEHIND
0,TRUE,FALSE,FALSE,MID
Perl <=>
연산자(때때로 "우주선 연산자"라고도 함)는 3방향 산술 비교를 수행합니다. 왼쪽 변이 오른쪽 변보다 엄격하게 작으면 -1을 반환하고, 같으면 0을, 그렇지 않으면 1을 반환합니다.
답변2
$ awk -F, 'BEGIN { OFS="," } NR==1 { print $0, "BMT" } NR>1 && $1>0 { print $0, "THROUGH" } NR>1 && $1==0 { print $0, "MID" } NR>1 && $1<0 { print $0, "BEHIND" }' inputfile > outputfile
또는 다른 옵션:
$ awk -F, 'BEGIN { OFS="," } NR==1 { print $0, "BMT" } NR>1 { if( $1 < 0 ) { $5="BEHIND" }; if( $1==0 ) { $5="MID" }; if( $1>0 ) { $5="THROUGH" }; print }' inputfile > outputfile
더 쉽게 읽을 수 있도록 형식이 변경된 실제 awk
스크립트(여기서 후자 버전을 확장하겠습니다):
BEGIN {
OFS="," # Set the Output Field Separator.
# This is the complement to `F,` which
# sets the Input Field Separator.
}
NR==1 { # For only the first record
print $0, "BMT" # Print exactly what we got, but add a new field, BMT
}
NR>1 { # For all records _after_ the first:
if( $1 < 0 ) { # This and the other if statements check
$5="BEHIND" # the value of the first field, and set
}; # the value of the to-be-newly-added fifth
if( $1==0 ) { # field accordingly.
$5="MID"
};
if( $1>0 ) {
$5="THROUGH"
};
print # Finally, print all our fields
}
답변3
밀러(http://johnkerl.org/miller/doc)
mlr --csv put 'if ($xcoord < 0) {$BMT="BEHIND"};
if ($xcoord == 0) {$BMT="MID"};
if ($xcoord > 0) {$BMT="THROUGH"}' input >./output
당신은
xcoord,m1,m2,m3,BMT
9,TRUE,FALSE,FALSE,THROUGH
-1,TRUE,FALSE,FALSE,BEHIND
0,TRUE,FALSE,FALSE,MID
내가 사용한 입력으로
xcoord,m1,m2,m3
9,TRUE,FALSE,FALSE
-1,TRUE,FALSE,FALSE
0,TRUE,FALSE,FALSE
답변4
$ perl -F, -pale '$_ .= "," . ("BMT", qw/MID THRU BEHIND/[$F[0] <=> 0])[$. > 1]' csvfile
xcoord가 23열에 있으면 $F[0]을 $F[22]로 바꾸세요.
설명을 보려면 Perl 솔루션에 대한 소개를 작성한 Kusalananda의 답변을 참조하세요.
결과:
xcoord,m1,m2,m3,BMT
9,TRUE,FALSE,FALSE,THRU
-1,TRUE,FALSE,FALSE,BEHIND
0,TRUE,FALSE,FALSE,MID
xcol=1; # the column number of xcoord
sed -e '
1s/$/,BMT/;1b
s/,/\n/'"$xcol"'
s/.*/,&,/
/,-[1-9][0-9]*\n/s/$/BEHIND/
/,0\n/s/$/MID/
/,[1-9][0-9]*\n/s/$/THRU/
s/\n/,/;s/,//
' csvfile