我有一个文件,其行类似于以下内容(不幸的是,这是另一个软件输出结果的唯一格式):
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 (/)
如果我将 改为a会更容易吗colon (:)
?
我为什么要问这个问题?我试图搜索是否/
是 .. 的子字符串$i
(如果答案是肯定的,那么我会将split()
$i 分成两部分,然后进行除法)。
我在其他地方读到,为了检查字段是否以$i
开头F
,他们使用if ($i~/^F/)
-- 所以我尝试了if ($i~///)
,然后if ($i~/"/"/)
,然后if ($i~/\//) (escaping / with a \)
等等。这些都不起作用。所以我认为/
是 Awk 中的一个特殊字符。为了避免特殊字符的复杂化,我想,让我用一下:
吧。
迭代字段并拆分每个字段/
。如果拆分恰好生成两个子字符串,请使用它们来计算字段的新值:
$ 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
Run Code Online (Sandbox Code Playgroud)
对于两位小数,请使用%.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
Run Code Online (Sandbox Code Playgroud)
类似地,使用Miller:
$ 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
Run Code Online (Sandbox Code Playgroud)
$ 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
Run Code Online (Sandbox Code Playgroud)
请注意,使用nidx
输入和输出格式时,默认的字段分隔符是单个空格字符。这意味着问题中显示的输入有 17 个字段,其中一些字段为空。这些都在输出中复制,这意味着空格被保留。