다음과 유사한 줄이 포함된 파일이 있습니다(불행히도 이것은오직다른 소프트웨어의 출력 결과 형식):
1 2 3 5/2 7 17/5 9 10/3 15
다음 줄로 바꿔야 합니다.
1 2 3 2.5 7 3.4 9 3.33 15
즉, GAWK가 나눗셈을 수행하고 분수(유리수)를 5/2, 17/5 and 10/3
소수 값으로 바꾸길 원합니다.2.5, 3.4 and 3.33.
여러 FS(필드 구분 기호)를 시도했지만 아무것도 작동하지 않습니다. GAWK를 사용하여 이를 수행하는 좋은 방법은 무엇입니까? 감사해요.
slash (/)
로 바꾸면 좀 더 편해질까요 colon (:)
?
내가 왜 이 질문을 하는 걸까요? /
..의 하위 문자열인지 검색하려고 합니다 . $i
(답이 '예'이면 split()
$i를 두 부분으로 나눈 다음 나누기를 수행합니다.)
필드가 -- $i
로 시작 하는지 확인하기 위해 다른 곳에서 읽었으므로 , then , then 등을 시도했습니다 . 이들 중 어느 것도 작동하지 않습니다. 그래서 Awk의 특별한 캐릭터인 것 같아요 . 특수 문자의 복잡함을 피하기 위해 이것을 사용하자고 생각했습니다 .F
if ($i~/^F/)
if ($i~///)
if ($i~/"/"/)
if ($i~/\//) (escaping / with a \)
/
:
답변1
필드를 반복하고 각 필드를 분할합니다 /
. 분할로 인해 정확히 두 개의 하위 문자열이 생성되는 경우 이를 사용하여 필드의 새 값을 계산합니다.
$ awk '{ for (i=1; i<=NF; ++i) if (split($i,a,"/")==2) $i = a[1]/a[2] };1' file
1 2 3 2.5 7 3.4 9 3.33333 15
소수점 이하 두 자리의 경우 %.2f
형식 지정자를 사용합니다 sprintf()
.
$ awk '{ for (i=1; i<=NF; ++i) { if (split($i,a,"/")==2) $i = sprintf("%.2f",a[1]/a[2]) } };1' file
1 2 3 2.50 7 3.40 9 3.33 15
마찬가지로,밀러:
$ mlr --nidx put 'for (k,v in $*) { a=splitnv(v,"/"); if (length(a)==2) { $[k]=a[1]/a[2] } }' file
1 2 3 2.500000 7 3.400000 9 3.333333 15
$ mlr --nidx put 'for (k,v in $*) { a=splitnv(v,"/"); if (length(a)==2) { $[k]=fmtnum(a[1]/a[2],"%.2f") } }' file
1 2 3 2.50 7 3.40 9 3.33 15
입력 및 출력 형식을 사용할 때 기본 필드 구분 기호 nidx
는 단일 공백 문자입니다. 이는 질문에 표시된 입력에 17개의 필드가 있으며 그 중 일부는 비어 있음을 의미합니다. 이는 출력에 복사되며 이는 공백이 유지됨을 의미합니다.
답변2
사용하기가 더 쉽습니다(또한 GNU 구현보다 더 많은 사전 설치된 시스템이 함께 제공됩니다 perl
).perl
gawk
awk
perl -pe 's{(\d+)/(\d+)}{sprintf "%.2f", $1/$2}ge'
또는:
perl -pe 's{\d+/\d+}{sprintf "%.2f", eval$&}ge'
s
숫자/숫자를 마지막 두 자리의 형식화된 나눗셈 결과로 바꿉니다 .
.
perl -pe 's{(?<!\S)\d+/\d+(?!\S)}{sprintf "%.2f", eval$&}ge'
숫자/숫자 앞 및/또는 뒤에 흰색이 아닌 S
리듬(예: 1/0x2
, ...)을 A1/2
그대로 둡니다.