我有一个文件,其行类似于以下内容(不幸的是,这是仅有的其他软件输出结果的格式):
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 中的一个特殊字符。为了避免特殊字符的复杂化,我想,让我用一下吧:
。
答案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
...)单独保留。