bash awk - 将负数转换为正数,反之亦然
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9852660/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
awk - Converting negative numbers to positive and vice versa
提问by user1290065
I have a file with structure like this:
我有一个结构如下的文件:
[05:58:10 08.12.1990] 125.441
[05:58:21 08.12.1990] -2.4158
...
Where everything but the last colummn is some sort of timecode (different for every file) and I need to convert the last number to its opposite, like this:
除了最后一列之外的所有内容都是某种时间码(每个文件都不同),我需要将最后一个数字转换为相反的数字,如下所示:
[05:58:10 08.12.1990] -125.441
[05:58:21 08.12.1990] 2.4158
...
I tried it with awk, but since my knowledge of awk is quite poor I didn't quite achieve it. I first tried to add negative numbers with this:
我用 awk 尝试过,但由于我对 awk 的了解很差,所以我没有完全实现它。我首先尝试用这个添加负数:
awk '{$NF=" "; NF--; printf awk '{$NF *= -1; print}'
; NF++; if ($NF ~ /^[0-9].*/){printf "-"; print $NF}}'
but since I throw the last column away with NF--, I can't get it back with NF++.
但是因为我用 NF-- 扔掉了最后一列,所以我无法用 NF++ 取回它。
Any help with this would be appreciated. Thank you.
对此的任何帮助将不胜感激。谢谢你。
回答by William Pursell
Try :
尝试 :
awk ' { if( $NF ~ /^-/ ){sub(/-/, "", $NF); print cat data | awk ' { if( $NF ~ /^-/ ){sub(/-/, "", $NF); print sed 's/ \([0-9.]*\)$/ -/;t;s/\(.*\)-//' file
[05:58:10 08.12.1990] -125.441
[05:58:21 08.12.1990] 2.4158
;}
else { $NF="-"$NF; print $ 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
}} '
[05:58:10 08.12.1990] -125.441
[05:58:21 08.12.1990] 2.4158
[05:59:30 08.13.2000] -0.94630008768741448848
;}
else {sub(/^[1-9]*.[1-9]*/,"-"$NF,$NF); print $ txr -c '@(collect)
@(cases)
[@date] @{sign /-?/}@num
@(or)
@(throw error "invalid data")
@(end)
@(output)
[@date] @(if (equal sign "") "-" "")@num
@(end)
@(end)' < data.txt
} } '
$ 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 ## Try to remove the negative sign.
s/\(\] \+\)-\(.*\)$//
## 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
;} else {sub(/^[1-9]*.[1-9]*/,"-"$NF,$NF); print [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
回答by wisent
what about:
关于什么:
sed -f script.sed infile
edit: as William Purssell suggested, improved version of this script:
编辑:正如 William Purssell 所建议的,这个脚本的改进版本:
[05:58:10 08.12.1990] -125.441
[05:58:21 08.12.1990] 2.4158
回答by potong
This might work for you:
这可能对你有用:
##代码##In essence:
在本质上:
- If the last field is separated by a space prepend a
- - Otherwise remove the last minus.
- 如果最后一个字段由空格分隔,则添加一个
- - 否则删除最后一个减号。
回答by Kaz
This is more robust than the hacky solutions that blindly flip a minus sign by column, because we are doing some pattern matching on what the data looks like (and we can increase the amount of detail, if necessary).
这比盲目地逐列翻转减号的hacky解决方案更强大,因为我们正在对数据的外观进行一些模式匹配(并且我们可以在必要时增加细节量)。
But the @(collect)skips stuff that does not match. One thing we can do is throw an exception if there is some oddly shaped row:
但是@(collect)跳过不匹配的东西。我们可以做的一件事是,如果有一些奇怪形状的行,则抛出异常:
回答by Birei
Using sed:
使用sed:
Content of script.sed:
内容script.sed:
Content of infile:
内容infile:
Run it like:
像这样运行它:
##代码##And result:
结果:
##代码##
