在Linux中减去两个文件的值

时间:2015-12-15 20:19:11

标签: awk grep diff

我有两个包含数字和文本的文件。两个文件中的文本是相同的。我想创建一个新文件,其中包含两个文件的平均数。

FileA.txt(超过10000行,超过1000个文本和数字)

External Host

FileB.txt(文本与FileA.txt相同)

textA
textB(10,2,2)
textC(2)
textD
.
.

FileNew.txt(具有FileA和FileB.txt的平均值)

textA
textB(0,0,4)
textC(4)
textD
.
.

一个请求是我不想更改任何文本。只需要更改数字。

我认为AWK或者差异化工作。

最佳,

Jaeyoung

2 个答案:

答案 0 :(得分:3)

也许你可以尝试这样:

paste 'FileA' 'FileB'|awk '{if($0!~/\([0-9]+,[0-9]+,[0-9]+\)/){print $1;next}{split($1,f1,/[(),]/);split($2,f2,/[(),]/)};print f1[1] "(",int((f1[2]+f2[2])/2) "," int((f1[3]+f2[3])/2) "," int((f1[4]+f2[4])/2) ")"}'

以可读的方式打破这个

创建一个名为awkscript的文件并附加这些行

#!/usr/bin/awk
{
if($0!~/\([0-9]+,[0-9]+,[0-9]+\)/){
    print $1;next}
{split($1,f1,/[(),]/);split($2,f2,/[(),]/)};
print f1[1] "(",int((f1[2]+f2[2])/2) "," int((f1[3]+f2[3])/2) "," int((f1[4]+f2[4])/2) ")"
}

现在调用你的脚本

paste 'FileA' 'FileB'|awk -f 'awkscript'

(粘贴在这里派上用场)

结果

textA
textB( 5,1,3)
textC(2)
textD
.
.

答案 1 :(得分:0)

TXR解决方案:

@(next :list @(weave (get-lines (open-file [*args* 0]))
                     (get-lines (open-file [*args* 1]))))
@(repeat)
@  (cases)
@text(@cnum0)
@text(@cnum1)
@    (do (let* ((num0 [mapcar toint (split-str cnum0 ",")])
                (num1 [mapcar toint (split-str cnum1 ",")])
                (avg (mapcar (op trunc (+ @1 @2) 2) num0 num1)))
           (put-line `@text(@{avg ","})`)))
@  (or)
@text
@text
@    (do (put-line text))
@  (end)
@(end)


$ txr avg.txr FileA.txt FileB.txt
textA
textB(5,1,3)
textC(3)
textD
.
.

此脚本处理文件,就好像它们是两个文件中包含行interleaved的文件一样。相应的文本必须完全匹配,否则程序将以失败的终止状态停止。与text(whatever)语法不匹配的行被假定为必须完全匹配的文本。

假设数字是整数,并且在平均中使用截断除法。

这个纯粹的Lisp解决方案简单地将行分为数字和非数字部分,平均相应的数字部分。使用浮点数学。 tok-str中的t参数告诉它保留与标记化正则表达式不匹配的中间部分。

(each ((line0 (get-lines (open-file [*args* 0])))
       (line1 (get-lines (open-file [*args* 1]))))
  (let* ((nregex #/(\d+|\d+\.\d+|\.\d+)([Ee][+\-]?\d+)?/)
         (chop0 (tok-str line0 nregex t))
         (chop1 (tok-str line1 nregex t))
         (out (mapcar (lambda (tok0 tok1)
                        (let ((n0 (tofloat tok0))
                              (n1 (tofloat tok1)))
                          (if (and n0 n1)
                            (/ (+ n0 n1) 2)
                            tok0)))
                      chop0 chop1)))
    (put-line `@{out ""}`)))

$ txr avg.tl  FileA.txt FileB.txt
textA
textB(5.0,1.0,3.0)
textC(3.0)
textD
.
.