将所有正值更改为负值,反之亦然,但在两个不同的文件中

将所有正值更改为负值,反之亦然,但在两个不同的文件中

我有两个数据文件one.txt并且two.txt在Linux系统上。我想将 中 的所有正值转换为负值one.txt,反之亦然two.txt,但仅限于第一列。请注意,数据也包含零。

one.txt是这样的:

   10 35.74
    8 35.74
    6 35.74
    4 35.74
    2 35.74
    0 35.74 

two.txt像这样

    -20 35.74
    -18 35.74
    -16 35.74
    -14 35.74
    -12 35.74
     -0 35.74

我想one.txt这样改变:

   -10 35.74
    -8 35.74
    -6 35.74
    -4 35.74
    -2 35.74
    -0 35.74

同样,我想将所有负值更改为正值two.txt

我尝试过awk '$1 *= -1' file.txt,但它搞砸了零。

我需要在两个不同的进程中执行这两个问题。因此,我更喜欢为每个问题使用两个不同的解决方案/代码,而不是在一个步骤中完成

答案1

您的尝试的一个小变体将会起作用:

awk '{ $1 *= -1 } 1' file.txt

问题在于awk '$1 *= -1'$1 *= -1被视为一个条件;应用其效果,但随后将其作为条件,因此仅当结果非零时才输出已处理的行。

添加大括号会导致将乘法应用于所有行,而 本身1会导致打印所有行。为了避免更改空行,您可以在乘法中添加一个条件:

awk 'NF { $1 *= -1 } 1' file.txt

如果您使用 Gawk1,您可以在更改之前检查第一列是否为数字:

awk 'typeof($1) == "strnum" { $1 *= -1 } 1' file.txt

POSIXLY_CORRECT1 并且环境中没有变量

答案2

这只是一个文本解析问题。将每行的第一个转换-+

$ sed 's/-/+/' two.txt 
    +20 35.74
    +18 35.74
    +16 35.74
    +14 35.74
    +12 35.74
     +0 35.74

并在每行的第一个数字之前添加一个-(您的文件似乎有前导空格):

$ sed -E 's/[0-9]/-&/' one.txt 
   -10 35.74
    -8 35.74
    -6 35.74
    -4 35.74
    -2 35.74
    -0 35.74 

如果您的文件没有问题中显示的前导空格,您可以将其简化为:

sed -E 's/^/-/' one.txt 

在所有情况下,您都可以使用-i就地编辑文件:

sed -i 's/-/+/' two.txt
sed -i -E 's/[0-9]/-&/' one.txt 

答案3

负 0 不适用于整数 C 数据类型。当数字没有小数部分时,awk 将其转换为字符串,就像使用printf("%ld").

要保留 的符号-0,您需要类似的东西:

awk '{$1 = sprintf("%g", -$1); print}'

Beware%g具有 6 位精度,对于大数字将切换到工程符号。%15g例如,您可以替换为以获得更高的精度。

您可以按文本方式进行操作,而无需在字符串和数字之间来回转换:

perl -pe 's{(-?)(?=\d)}{$1 ? "" : "-"}e'

这还有一个好处是不改变字段之间的间距。您还可以传递一个-i选项来perl就地编辑文件(然后需要将其作为参数传递,而不是标准输入)。

答案4

$ awk '!sub(/-/,"",$1){$1="-"$1} 1' one.txt
-10 35.74
-8 35.74
-6 35.74
-4 35.74
-2 35.74
-0 35.74

$ awk '!sub(/-/,"",$1){$1="-"$1} 1' two.txt
20 35.74
18 35.74
16 35.74
14 35.74
12 35.74
0 35.74

相关内容