탭으로 구분된 파일의 모양 변경

탭으로 구분된 파일의 모양 변경

다음과 같은 파일이 있습니다.

 Time   Flag
 0.65   5.885581e-01
 0.56   5.847484e-01
 0.58   5.278409e-01
 0.57   1.140746e+00
 1.00   0
 0.00   0
 1.00   1
 0.00   0

하지만 그것은 내가 글을 쓸 때 무언가를 바꾸는 것을 잊어버렸기 때문입니다. 따라서 타이밍의 절반은 플래그 열에서 끝나고 플래그의 절반은 시간 열에서 끝납니다. 그랬어야 했어

 Time Flag
 0.65   1
 0.59   0
 0.56   0
 0.58   0
 0.58   1
 0.53   1
 0.57   0
 1.14   0

따라서 이 작은 예에서는 처음 4개 행이 첫 번째 열이 되어야 합니다. 마지막 4개 행은 두 번째 열이 되어야 합니다. 각 열의 요소 중 절반은 원본 파일에서 올바른 형식(교대 방식)으로 지정되어 있습니다. 모양을 바꾸고 형식을 바꾸는 가장 쉬운 방법은 무엇입니까?

답변1

$ awk 'NR > 1 { d[++n] = $1; d[++n] = $2 } END { print "Time", "Flag"; for (i = 1; 2*i <= n; ++i) printf "%.2f%s%d%s", d[i], OFS, d[n/2 + i], ORS }' file
Time Flag
0.65 1
0.59 0
0.56 0
0.58 0
0.58 1
0.53 1
0.57 0
1.14 0

awk코드는 모든 데이터를 행 단위로 읽어 배열의 연속 요소로 읽습니다 d(헤더 건너뛰기).

END블록 에서 헤더가 인쇄된 다음 i1에서 배열 길이의 절반까지 반복하여 d인덱스(시간 값)의 값 과 마크 (플래그 값) i의 값을 인쇄합니다. n/2 + i시간 값이 소수점 이하 두 자리의 부동 소수점 값으로 인쇄되고 플래그 값이 정수로 인쇄되도록 출력 형식을 완료합니다.

OFS변수는 ORS기본 출력 필드와 레코드 구분 기호를 보유합니다(기본값은 공백과 줄 바꿈). 탭으로 구분된 출력의 경우 awk -v OFS='\t' '{ ... }' file.

참고로 이 awk코드는 독립형 스크립트로 작동합니다.

#!/usr/bin/awk -f

NR > 1 {
    d[++n] = $1
    d[++n] = $2
}

END {
    print "Time", "Flag"

    for (i = 1; 2*i <= n; ++i)
        printf "%.2f%s%d%s", d[i], OFS, d[n/2 + i], ORS
}

답변2

OP에는 문제가 파일을 반으로 분할하고 각 반을 복구한 다음 다시 결합해야 한다고 명시되어 있지 않지만 해당 지식 없이 이를 수행하는 방법을 알고 싶습니다.

나는 정말 좋아한다csvkit특히GoCSV선언적 파이프라인 처리용.

변환/설정

첫 번째 단계는 고정 너비 샘플 데이터를 CSV로 변환하는 것입니다. csvkit을 사용하면 열 너비 패턴을 지정할 수 있습니다...

스키마.csv

column,start,length
Time,0,4
Flag,7,13

그런 다음 CSV로 변환합니다.

in2csv -s schema.csv input.txt > input.csv

분리 및 전치

입력을 플래그와 시간이라는 범주별로 나누고 싶습니다. 그런 다음 각 범주에 대해 단일 행 CSV 집합을 만듭니다(다음 단계의 전치를 위해).

gocsv filter -c 2 --regex "^[01]$" input.csv | 
gocsv split --max-rows 1 --filename-base flags

보완적인 시간에는 동일한 패턴이 사용됩니다 --exclude.

gocsv filter -c 2 --regex "^[01]$" --exclude input.csv | 
gocsv split --max-rows 1 --filename-base times

그러면 다음과 같은 파일 세트가 생성됩니다.

ls flags-*.csv                                     
flags-1.csv  flags-2.csv  flags-3.csv  flags-4.csv

각각은 다음과 같습니다.

로고-1.csv

Time,Flag
1.00,0

또는:

times-4.csv

Time,Flag
0.57,1.140746e+00

헤더는 Time,Flag그다지 중요한 것은 아니지만, 헤더가 존재하고 전치된 구조에 영향을 미치는지 보는 것이 중요합니다.

각 파일에 대해 전치를 반복하고 두 번째 열을 선택하고(잘못된 헤더가 첫 번째 열이 되기 때문에) 적절한 헤더로 마무리합니다.

for FILE in flags-*; do 
  gocsv transpose $FILE | 
  gocsv select -c 2 | 
  gocsv cap --names Flag \
  > trans_$FILE; 
done

for FILE in times-*; do
  gocsv transpose $FILE |
  gocsv select -c 2 |
  gocsv cap --names Time \
  > trans_$FILE;
done

기둥으로 쌓인

플래그와 시간을 자체 열에 쌓습니다.

gocsv stack trans_flags*  > col_flag.csv

gocsv stack trans_times*  > col_time.csv

그런 다음 함께 압축합니다(저는 그냥 사용하겠습니다).csvlook더 예쁜 Markdown 테이블이 있지만 숫자도 정규화하기 때문입니다! ):

gocsv zip col_time.csv col_flag.csv > output.csv
csvlook output.csv
시간 배너
0.650… 1
0.589… 0
0.560… 0
0.585… 0
0.580… 1
0.528… 1
0.570… 0
1.141… 0

이것은 귀엽다.

그러나 마지막 단계는 GoCSV에 내장된(나에게 새로운) SPRIG 템플릿과 round함수를 사용하여 부동 소수점, 정수 및 과학적 표기법을 정리하는 것입니다. 원래 열을 기반으로 새 열을 추가한 다음 새 열이나 서식이 지정된 열만 선택합니다.

cat output.csv |
gocsv add -n Time -t "{{round .Time 2}}" |
gocsv add -n Flag -t "{{round .Flag 0}}" |
gocsv select -c 3- |
gocsv tsv

우리는 다음을 얻었습니다:

Time    Flag
0.65    1
0.59    0
0.56    0
0.58    0
0.58    1
0.53    1
0.57    0
1.14    0

관련 정보