awk - 将负数转换为正数,反之亦然

时间:2012-03-24 14:52:39

标签: bash sed awk

我有一个结构如下的文件:

[05:58:10 08.12.1990] 125.441
[05:58:21 08.12.1990] -2.4158
...

除了最后一个列之外的所有内容都是某种时间码(每个文件都不同),我需要将最后一个数字转换为相反的数字,如下所示:

[05:58:10 08.12.1990] -125.441
[05:58:21 08.12.1990] 2.4158
...

我用awk尝试过,但由于我对awk的了解很差,所以我没有完成它。 我首先尝试用这个添加负数:

awk '{$NF=" "; NF--; printf $0; NF++; if ($NF ~ /^[0-9].*/){printf "-"; print $NF}}'

但是因为我用NF--扔掉了最后一栏,我无法用NF ++取回它。

任何有关此的帮助将不胜感激。谢谢。

5 个答案:

答案 0 :(得分:5)

尝试:

awk '{$NF *= -1; print}'

答案 1 :(得分:2)

怎么样:

awk '  { if( $NF ~ /^-/ ){sub(/-/, "", $NF); print $0;} 
         else {sub(/^[1-9]*.[1-9]*/,"-"$NF,$NF); print $0}  } '


$ cat data 
[05:58:10 08.12.1990] 125.441
[05:58:21 08.12.1990] -2.4158
$ cat data | awk '  { if( $NF ~ /^-/ ){sub(/-/, "", $NF); print $0;} else {sub(/^[1-9]*.[1-9]*/,"-"$NF,$NF); print $0} }'
[05:58:10 08.12.1990] -125.441
[05:58:21 08.12.1990] 2.4158

编辑: 正如William Purssell建议的那样,改进了这个脚本的版本:

cat data | awk '  { if( $NF ~ /^-/ ){sub(/-/, "", $NF); print $0;} 
         else { $NF="-"$NF; print $0}} '
[05:58:10 08.12.1990] -125.441
[05:58:21 08.12.1990] 2.4158
[05:59:30 08.13.2000] -0.94630008768741448848

答案 2 :(得分:1)

这可能对您有用:

sed 's/ \([0-9.]*\)$/ -\1/;t;s/\(.*\)-/\1/' file
[05:58:10 08.12.1990] -125.441
[05:58:21 08.12.1990] 2.4158

本质上:

  • 如果最后一个字段以空格分隔,则前缀为-
  • 否则删除最后一个减号。

答案 3 :(得分:0)

使用sed

script.sed的内容:

## Try to remove the negative sign.
s/\(\] \+\)-\(.*\)$/\1\2/

## If last substitution succeed, goto label 'a'.
ta

## If last substitution failed, there was not negative sign, so
## it is a positive number, I will have to add the sign just 
## before it.
s/\] \+/&-/

## Label 'a' at end of script. Here print line and read next one.
:a

infile的内容:

[05:58:10 08.12.1990] 125.441
[05:58:21 08.12.1990] -2.4158

像以下一样运行:

sed -f script.sed infile

结果:

[05:58:10 08.12.1990] -125.441                                                                                                                                                                                                               
[05:58:21 08.12.1990] 2.4158

答案 4 :(得分:0)

http://www.nongnu.org/txr

$ txr -c '@(collect)
[@date] @{sign /-?/}@num
@(output)                                                         
[@date] @(if (equal sign "") "-" "")@num   
@(end)   
@(end)' < data.txt
[05:58:10 08.12.1990] 125.441
[05:58:21 08.12.1990] -2.4158
[05:59:30 08.13.2000] 0.94630008768741448848

这比通过列盲目地减去减号的hacky解决方案更强大,因为我们正在对数据的外观进行一些模式匹配(如果需要,我们可以增加细节数量)。

但是@(collect)会跳过不匹配的内容。如果有一些形状奇特的行,我们可以做的就是抛出异常:

$ txr -c '@(collect)
@(cases)
[@date] @{sign /-?/}@num
@(or)                                      
@(throw error "invalid data")
@(end)   
@(output)
[@date] @(if (equal sign "") "-" "")@num
@(end)
@(end)' < data.txt