gnuplot으로 보내기 전에 전처리 중인 데이터 파일이 있습니다. 헤더 행과 여러 데이터 행으로 구성되며 많은 데이터 유형 열이 있습니다. 처음 세 개의 열은 항상 동일한 유형과 순서를 갖습니다. 총 열 수는 파일 내에서는 일정하지만 파일 간에는 일정하지 않습니다. seqno는 1부터 시작하는 것이 보장되지 않지만 항상 단조롭게 증가합니다.
데이터 파일에서 원하는 위치에 헤더 행을 삽입하는 스크립트가 있는데 현재 일치하는 항목에 따라 해당 헤더를 변경할 수 있기를 원합니다. 특히 $i 변수를 네 번째 변수에 추가하고 싶습니다. 5번째, ..endth 열이 헤더입니다. 그 외에는 각 위치의 제목이 동일합니다.
이는 스크립트로 실행되므로 헤더에 포함된 열 수를 확인하기 위해 헤더를 전처리해야 하는 경우 쉽게 수행할 수 있습니다.
필요한 헤더 교체가 없는 현재 스크립트는 다음과 같습니다(마지막에 다른 헤더 예제가 있음).
header=$(head -n1 $input)
awk -v i=3 -v hdr="$header" 'NR>1 && $i!=p {print "\n\n"hdr}{p=$i} 1' ${input} > ${output}
내 입력 예는 다음과 같습니다
#filename seqno phasename a b c scale Rwp
blah_001.xye 1 corundum 3 3 12 0.001 3
blah_002.xye 2 corundum 3.1 3.1 12.1 0.002 3.5
blah_003.xye 3 corundum 3.2 3.2 12.2 0.001 3.1
blah_001.xye 2 silcon_NIST 5.4 5.4 5.4 0.002 3
blah_002.xye 3 silcon_NIST 5.41 5.41 5.41 0.004 3.5
blah_003.xye 4 silcon_NIST 5.42 5.42 5.42 0.002 3.1
내 현재 출력은 다음과 같습니다
#filename seqno phasename a b c scale Rwp
blah_001.xye 1 corundum 3 3 12 0.001 3
blah_002.xye 2 corundum 3.1 3.1 12.1 0.002 3.5
blah_003.xye 3 corundum 3.2 3.2 12.2 0.001 3.1
#filename seqno phasename a b c scale Rwp
blah_001.xye 2 silcon_NIST 5.4 5.4 5.4 0.002 3
blah_002.xye 3 silcon_NIST 5.41 5.41 5.41 0.004 3.5
blah_003.xye 4 silcon_NIST 5.42 5.42 5.42 0.002 3.1
내가 원하는 출력은 다음과 같습니다.
#filename seqno phasename corundum_a corundum_b corundum_c corundum_scale corundum_Rwp
blah_001.xye 1 corundum 3 3 12 0.001 3
blah_002.xye 2 corundum 3.1 3.1 12.1 0.002 3.5
blah_003.xye 3 corundum 3.2 3.2 12.2 0.001 3.1
#filename seqno phasename silcon_NIST_a silcon_NIST_b silcon_NIST_c silcon_NIST_scale silcon_NIST_Rwp
blah_001.xye 2 silcon_NIST 5.4 5.4 5.4 0.002 3
blah_002.xye 3 silcon_NIST 5.41 5.41 5.41 0.004 3.5
blah_003.xye 4 silcon_NIST 5.42 5.42 5.42 0.002 3.1
hdr
내가 하고 싶은 일: awk에서 awk 변수를 변경하여 입력 파일에 삽입하기 전에 $i
변수의 마지막 네 번째 열에 변수를 추가 하려면 어떻게 해야 합니까?hdr
다른 파일에서 처리하기 위한 다른 예시 헤더
#filename seqno phasename temp temp_err csL csL_err csG csG_err strL strL_err strG strG_err B_Na B_Na_err B_Mg B_Mg_err B_F B_F_err B_H B_H_err B_O B_O_err B_Fe B_Fe_err F_occ F_occ_err Na_x Na_x_err Na_z Na_z_err F1_x F1_x_err F1_y F1_y_err F1_z F1_z_err F2_x F2_x_err F2_z F2_z_err a1 a1_err a2 a2_err a3 a3_err a4 a4_err a5 a5_err a6 a6_err a7 a7_err s1 s1_err s2 s2_err s3 s3_err a a_err b b_err c c_err al al_err be be_err ga ga_err volume volume_err mass mass_err MAC MAC_err density density_err LAC LAC_err Lvol Lvol_err e0 e0_err scale scale_err wt% wt%_err num_area num_area_err r_bragg r_bragg_err r_wp r_wp_err r_exp r_exp_err gof gof_err
#filename seqno phasename csL csL_err strG strG_err a a_err b b_err c c_err al al_err be be_err ga ga_err volume volume_err mass mass_err MAC MAC_err density density_err LAC LAC_err Lvol Lvol_err e0 e0_err scale scale_err wt% wt%_err num_area num_area_err r_bragg r_bragg_err r_wp r_wp_err r_exp r_exp_err gof gof_err
#filename seqno phasename csG strL F1_x F1_y F1_z volume gof
답변1
$ awk -f script.awk file
#filename seqno phasename corundum_a corundum_b corundum_c corundum_scale corundum_Rwp
blah_001.xye 1 corundum 3 3 12 0.001 3
blah_002.xye 2 corundum 3.1 3.1 12.1 0.002 3.5
blah_003.xye 3 corundum 3.2 3.2 12.2 0.001 3.1
#filename seqno phasename silcon_NIST_a silcon_NIST_b silcon_NIST_c silcon_NIST_scale silcon_NIST_Rwp
blah_001.xye 2 silcon_NIST 5.4 5.4 5.4 0.002 3
blah_002.xye 3 silcon_NIST 5.41 5.41 5.41 0.004 3.5
blah_003.xye 4 silcon_NIST 5.42 5.42 5.42 0.002 3.1
script.awk
어디
BEGIN { OFS = "\t" }
/^#/ {
# save header fields
for (i = 1; i <= NF; ++i)
header[i] = $i
next
}
# if column 2 contains a lower number than the previous line
# (or if no previous line with data), then output header
$2 < col2 || !col2 {
# output blank line if needed
if (print_blank) {
print ""
}
print_blank = 1
# print first three headers as-is
for (i = 1; i <= 3; ++i)
printf("%s%s", header[i], OFS)
# prepend column three to remaining headers
for (i = 4; i < NF; ++i)
printf("%s_%s%s", $3, header[i], OFS)
printf("%s_%s%s", $3, header[NF], ORS)
}
# print all lines and save value from column 2
{ col2 = $2; print }
스크립트는 입력 데이터의 헤더를 배열에 저장합니다 header
. 두 번째 열의 값이 이전 행의 두 번째 열 값보다 낮은 경우 데이터를 출력하기 전에 새 헤더를 출력합니다. 첫 번째 제목이 아닌 이상 제목 앞에 빈 줄이 있습니다. 변수 열 이름은 세 번째 필드의 이름에서 가져옵니다.
이 스크립트는 매개변수를 사용하지 않습니다.
답변2
Phase 이름 그룹이 마지막 Phase보다 큰 seqno로 시작될 가능성이 있는 경우 seqno에 의존하지 못할 수도 있지만 Phasename에 의존하는 것이 더 나을 수도 있습니다. Kusalananda가 제안한 적응을 시도해 볼 수도 있습니다.
awk '
FNR == 1 {split ($0, header)
next
}
$3 != LAST {printf TMPRS; TMPRS = ORS
for (i = 1; i <= NF; ++i) printf ("%s%s%s", (i>3)?$3"_":_, header[i], (i==NF?ORS:OFS))
}
{LAST = $3
print
}
' OFS="\t" filename1 filename2