入力ファイル
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
ライナーの1つをデバッグする - いくつかの小さな質問:
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つ以上のシーケンスである各レコードからトークンを抽出します。これは、先頭と末尾のスペース/改行が無視されることを意味します。したがって、列1が欠落すると、列2の値が列1になります。
区切り記号正規表現を使用すると、真の/ +/
区切り動作を取得できます。先行および末尾のスペースを含むレコードが1 2 3 4
考慮されます<SEP>1<SEP>2<SEP>3<SEP>4<SEP>
。したがって""
、、、"1"
...、、"4"
6つのフィールドがあります""
。最初のフィールドの前にフィールドが 1 つ、<SEP>
最後のフィールドの後にフィールドが 1 つあります。
ただし、最初のレコードにフィールドがない場合は、明らかにデフォルト値が必要です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
'