csv의 많은 값을 소수점 이하 3자리로 반올림합니다(printf?)

csv의 많은 값을 소수점 이하 3자리로 반올림합니다(printf?)

다음과 같은 붙여넣기 명령이 있습니다. paste -d , file1.csv file2.csv file3.csv

file2.csv에는 다음과 같은 숫자가 포함되어 있습니다.

0.2
0.3339
0.111111

file2.csv의 값에 다음과 같이 소수점 이하 3자리가 포함되기를 원합니다.

0.200
0.334
0.111

값의 경우 다음과 같이 작동합니다.

printf "%.3f" "0.3339"->0.334

그러나 이것은 file2.csv의 여러 값에 대해서는 작동하지 않습니다.

paste -d , file1.csv <(printf %s "%.3f" "$(< file2.csv)") file3.csv

어쩌면 좋은 해결책이 있을까요?

답변1

numfmt여기서 유용해 보이는 GNU coreutils 도구 모음의 일부인 GNU Utilities라는 GNU 유틸리티가 있습니다 . 숫자 값의 형식을 지정할 수 있으며, 다음 명령은 형식 문자열 ("소수점 세 자리까지의 정밀도를 갖는 부동 소수점 값")을 file2.csv사용하여 모든 값의 형식을 지정합니다. 형식화된 값은 표준 출력에 인쇄됩니다.printf%.3f

$ numfmt --format=%.3f <file2.csv
0.200
0.334
0.112

보시다시피 기본적으로 "0부터 시작하는" 반올림을 사용하지만 다음을 사용하여 변경할 수 있습니다 --round=nearest.

$ numfmt --format=%.3f --round=nearest <file2.csv
0.200
0.334
0.111

paste다음과 같이 프로세스 대체를 사용하여 명령에 삽입 할 수 있습니다 .

paste -d , file1.csv <( numfmt --format=%.3f --round=nearest <file2.csv ) file3.csv

파일이 "단순"하지 않은 CSV인 경우, 즉 인용된 필드가 포함될 수 있는 경우 CSV 인식 도구를 사용해야 할 수도 있습니다.밀러( mlr) 데이터 처리. 위의 두 번째 예는 Miller 표현식 numfmt(형식 문자열 사용)의 함수를 사용하여 아래에서 다시 생성됩니다.fmtnum()putprintf

$ mlr --csv -N put '$1 = fmtnum($1, "%.3f")' file2.csv
0.200
0.334
0.111

--csv옵션을 사용하면 -NMiller는 헤더 없는 CSV로 입력을 읽고 출력을 쓸 수 있습니다.

답변2

printf거의 다 끝났습니다. 소수점 오른쪽에 제로 패딩을 알려주면 됩니다 .

$ cat 736678.txt
0.2
0.3339
0.111111
$ for value in $( cat 736678.txt ); do printf "%.3f\n" "$value"; done
0.200
0.334
0.111

형식 문자열은 %.3f"이 지점 오른쪽에 정확히 소수점 세 자리가 있는 부동 소수점 숫자"를 의미합니다.

답변3

이를 사용 awk하여 모든 읽기, 서식 지정 및 붙여넣기 작업을 수행할 수 있습니다.

LC_ALL=C awk '
  {
    getline f2 < "file2.csv"
    getline f3 < "file3.csv"
    printf "%s,%.3f,%s\n", $0, f2, f3
  }' file1.csv

출력에서 원하는 만큼의 행을 얻을 수 있습니다 file1.csv( 0.000파일 2에 더 적은 행이 있으면 파일 3에 빈 문자열이 있음).

일부 구현 awk(GNU 포함)은 변수가 환경에 존재할 때 입력 및 출력에서 ​​로케일의 10진수 기본 문자를 존중합니다. 예를 들어, 프랑스어 또는 독일어 로케일에서는 십진수 기수 문자가 인식되지 않고 가비지로 처리되는 것으로 해석되어 CSV 형식을 깨는 출력을 얻게 됩니다.awkPOSIXLY_CORRECT,.1.2e51.2e51,000

따라서 위의 내용은 10진수 기수 문자가 있는 위치 LC_ALL=C로 로케일을 수정합니다 .C.

관련 정보