
입력 파일
CARD SG CLASS ATT
11 0 DAS YES
CARD SG CLASS ATT
12 0 ECT YES
CARD SG CLASS ATT
13 0 VAS YES
1 DAS NO
CARD SG CLASS ATT
14 0 SAT YES
CARD SG CLASS ATT
15 0 CDT YES
1 VEG YES
2 GAT NO
예상 출력:
CARD SG CLASS ATT
11 0 DAS YES
12 0 ECT YES
13 0 VAS YES
13 1 DAS NO
14 0 SAT YES
15 0 CDT YES
15 1 VEG YES
15 2 GAT NO
내가 뭘 한거지:
awk ' /YES|NO/{VAL=$1};/ATT/{Print "CARD" "SG" "CLASS" "ATT" };/YES|NO/{ print VAL, $2, $3, $4} ' SCGR.txt | column -t
11 0 DAS YES
12 0 ECT YES
13 0 VAS YES
1 DAS NO
14 0 SAT YES
15 0 CDT YES
1 VEG YES
2 GAT NO
도와주세요
답변1
다음을 시도해 보십시오(모든 헤더 행이 정확히 동일하다고 가정).
awk ' NR==1{header=$0; count=NF; print; next}
($0~header) {next}
(NF==count) {col1=$1}
(NF<count) {printf("%s",col1)}
1 ' infile | column -t
답변2
하나의 ligner 디버깅 -- 몇 가지 사소한 문제:
Print
--print
/ATT/{Print "CARD" "SG" "CLASS" "ATT" }
--/ATT/{print}
또는/ATT/;
/YES|NO/{VAL=$1}
또한 3개 필드 기록에서 트리거되어 이전에 저장된 값을 정리합니다. (순서를 바꾸거나$4 ~ /YES|NO/
)
변형:
awk 'NF==4{v=$1;print} NF==3{print v,$0}'
추가 헤더 제거 및 들여쓰기:
awk '/^CARD/ && NR>1 { next }
NF==4 { v=$1;print }
NF==3 { print v,$0 }'
답변3
열 정렬에 신경 쓰지 않고 공백으로 구분된 정규화된 데이터만 원하는 경우 기본 패턴은 다음과 같습니다.
awk -F' +' '{ $1 = ($1 ~ /^$/ ? prev : $1); prev = $1; print }'
기본 공백과 동일하지 않은 사용자 정의 필드 구분 기호를 설정하면 필드가 실제로 분리됩니다. 레코드가 구분 기호와 일치하는 항목으로 시작하면 빈 필드가 구분됩니다.
기본적으로 Awk는 분리되지 않습니다. 토큰화합니다. 각 레코드에서 하나 이상의 공백/줄바꿈 문자가 아닌 문자의 시퀀스인 토큰을 추출합니다. 이는 선행 및 후행 공백/개행이 무시됨을 의미합니다. 따라서 열 1이 누락된 경우 열 2의 값이 열 1이 됩니다.
구분 정규식을 사용하면 / +/
진정한 분리 동작을 얻을 수 있습니다. 와 같은 선행 및 후행 공백이 있는 레코드 1 2 3 4
는 로 처리됩니다 <SEP>1<SEP>2<SEP>3<SEP>4<SEP>
. 따라서 ""
, "1"
, ..., "4"
, 6개의 필드가 있습니다 ""
. 첫 번째 앞 <SEP>
과 마지막 뒤에 필드가 있습니다 .
그런데 첫 번째 레코드에 누락된 필드가 있을 수 있는 경우에는 분명히 에 대한 기본값이 필요합니다 prev
. 또한 우리는 논리가 제목에 적용되는 것을 원하지 않습니다. 또한 삼항 연산자를 :로 바꾸겠습니다 if
.
awk 'BEGIN { FS = " +"; prev = 0 }
NR == 1
NR > 1 { if ($1 == "") $1 = prev
print
prev = $1 }'
FOO BAR BAZ
FOO BAR BAZ
2 3 4
0 2 3 4
1 2 3 4
1 2 3 4
2 3 4
1 2 3 4
답변4
교육용으로만sed님의 결정
sed '
1b #output 1st line (header)
$!N #add next line to operate 2 lines altogether
s/\(.*\)\n\(CARD.*\)/\2\n\1/ #move line with CARD to first place
/^CARD/D #delete line with CARD and go to start
s/^\(\([0-9]*\s*\).*\n\)\s\s*/\1\2/
#repeat 1st field of 1st line if empty in 2nd
/\n/{P;D} #print&remove 1st line, go to start
'