如何合并两列中的值?


11

我有以下格式的文件:

$ cat /tmp/raw
2015-01   5000   1000
2015-02   6000   2000
2015-03   7000   3000

现在,我想要从每行的第2列和第3列中获取组合值,以便结果如下:

2015-01   6000
2015-02   8000
2015-03   9000

我试过了,但它只显示文件中的最后一个值,如2015-03值。

Answers:


11

您可以尝试使用awk

awk '{ print $1, $2 + $3; }' /tmp/raw

结果将是(我认为2015-03的值应为10000):

2015-01 6000
2015-02 8000
2015-03 10000

1
我不敢相信我会这么快就收到答复:O,我从未在任何其他论坛上得到过如此迅速的答复:)谢谢,命令运行得很好:)
Syed Jahanzaib 2015年

@SyedJahanzaib,如果此答案解决了您的问题,请花点时间接受一下,方法是单击左侧的复选标记。这会将问题标记为已回答,并且是在Stack Exchange网站上表达感谢的方式。
terdon

对不起,我忘了标记答案。并且也感谢所有其他人宝贵的时间和答复,他们也帮助我学习了使用不同方法实现目标的方法:)
Syed Jahanzaib 2015年

@SyedJahanzaib,尽管我为这个答案赢得了不错的徽章,但我认为更精确,更全面的解决方案是terdon的答案。
taliezin

16

以下是几种方法:

  1. 另一种awk方法

    awk '{$2+=$3;}NF--' file
    
  2. 佩尔

    perl -lane 'print "$F[0] ",$F[1]+$F[2]' file
    

    要么

    perl -ape 's/$F[1].*/$F[1]+$F[2]/e' file
    
  3. Shell(比上述速度慢/效率低)

    while read a b c; do echo "$a $((b + c))"; done < file
    

2
$2+=$3可能更笨拙。
123

@ User112638726确实是。谢谢。
terdon

3
您也可以使用,awk '{$2+=$3}NF--'因此仍然没有空白字段3徘徊。虽然那只是我的偏爱,但其过于相似,以至于无法单独发表答案:)
123

1
@ User112638726现在我什至没有想到过。非常整洁,谢谢!
terdon

我写这个给你。注意如何不仅sed以某种方式设法了解领域 -即使定义字段上的苍蝇,而中W / -但是,因为显然的情况下,Unix的正则表达式匹配的整个概念实际上是基于把一个字符串转换成根据模式!谁知道?
mikeserv

5
sed 's/[^ ]* */[&]P/;s//&+pc/3'|dc

...印刷品...

2015-01   6000
2015-02   8000
2015-03   10000

所以上述我声明一个正则表达式,其限定一个场范围,它由一个的*可变长度,其是字符的单个序列^不<空间>由紧接其后*的可变长度,其是字符的单个序列<空格>。此声明是针对sed的模式空间应用的,该模式空间是一个字符串(默认情况下)\n输入中出现的每个斜线字符定界,并且每次出现时都会用下一个递归替换(默认情况下)

该声明的接口是双重的,并且在每个级别上,至少一个国际IEEE官方标准委员会全面监管和指定,以确保可预测地应用sed命令语法。例如,在这种情况下,使用address 命令(始终是任何ubstitution命令的第一个组件应用sed的API语法,但更基本的API会将其内容解释为为该命令指定的子集功能在标准C库//sed s///regcomp()

我可以自信地做出这些声明,因为sed不是只是一个程序,而相反,编译后的可执行文件命名sed我的类Unix机器是执行的明确定义,在历史上建立的,与标准控制的sed 应用我的系统的regular-的表达式匹配库。


sed规格:

sed实用程序应支持XBD基本正则表达式中描述的BRE 。

...我们找到的地方...

无论BREs里面和ERES通过在POSIX.1-2008下的系统接口的体积正则表达式匹配的接口支持regcomp()regexec()以及相关的功能。

调用的应用程序regcomp()将显示一个模式字符串,并...

... [ regcomp()该函数应编译pattern参数所指向的字符串中包含的正则表达式,并将结果放入结构preg ...

为此,该应用程序将引用regcomp()的伴随函数...

... [t] regexec()该函数将string指定的以空值终止的字符串与通过先前调用... 初始化的已编译正则表达式preg进行比较regcomp()

... regexec()应当[一个]阵列的子串的偏移的元素填充字符串对应于\(括号内的子表达式\)图案 ... 图案本身算作一个子表达式...

... [T]他regexec()函数必须在所有填写nmatch的元素pmatch,其中nmatchpmatch由应用程序提供的,即使某些元素pmatch不对应的子表达式的模式


所以当我做...

/[^ ]* */

... sed首先编译正则表达式并将结果存储在内存中,然后再将存储在那里的已编译自动机应用到我的模式空间的内容,以执行命令所需的次数。每次执行时,结果都是一个或多个以null分隔的字段的数组,这些字段以所返回的偏移量定界regexec()

当我做...

//

...以指示应该使用最近定义的正则表达式,sed可以regexec()再次调用以重新使用预编译的正则表达式,但是这次可以将其应用于更改后的字符串参数,或者按照我的命令应用新的nmatch参数。

更具体地说...

  • s/[^ ]* */[&]P/
    • 用左方括号,然后替换本身,然后是右方括号后跟一个字符,以替换模式空间中第一次出现的模式[&]P
  • s//&+pc/3
    • 再次应用上次使用的正则表达式到当前模式空间,并更换3的第三次出现模式在图案空间&本身,随后所附的字符串+pc

因此,对于sed给定的示例数据,对于的输入的每一行,它都会写入其stdout:

[2015-01   ]P5000   1000+pc
[2015-02   ]P6000   2000+pc
[2015-03   ]P7000   3000+pc

这可能看起来很奇怪,但dc计算器报价在方括号内输入和P命令都将打印堆栈的顶部而不附加一个\newline和随后弹出的输入堆栈了这一关。

因此,以第一行为例dc

  • [2015-01 ]P
    • PRint并弹出堆栈顶部
  • 5000
    • 将数字5000推到堆栈顶部,然后将堆栈上当前的所有元素(现在没有)向下推一。
  • 1000
    • 同上,但这次主堆栈顶部的数字5000向下推了一个,成为堆栈上的第二个元素。
  • +
    • 将堆栈上的前两个数字相加,将这两个数字从堆栈中弹出,然后将总和推入堆栈的顶部。
    • 这将导致仅包含数字的堆栈6000
    • 如果堆栈上的前两个元素之一是[字符串,则这是语法错误]
  • p
    • p使堆栈顶部紧随其后,然后附加附加的\newline,而不会将其从堆栈中弹出。
  • c
    • c学习堆栈

我相信它可以,但是我无法解析。总体而言,您要为直流设置一个附加项。第一种模式很有意义。我认为它与日期和尾随空格匹配,但是我没有把它放在字符类括号([&])中。如果您能清楚地说明这一点,那就太好了。

1
@Joe-更好吗?
mikeserv

哇!这更有意义(并且向我展示了我需要学习更多的东西。)尤其是,我从来没有注意到使用//来重用当前模式。这是您阅读并忘记的事情,直到遇到实际示例为止。非常感谢。看到一个微妙的命令可以包装多少功率以及解释它需要花费多少,这让我感到很开心。
2015年

@Joe-好吧……也许我有点过分了……
mikeserv
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.