Linux 中两个文件的值相减

Subtracting values on two files in Linux

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

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

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

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

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

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

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

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

我认为 AWK 或 diff 可以胜任这项工作。

最佳,

在玹

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
.
.

也许您可以这样尝试:

paste 'FileA' 'FileB'|awk '{if([=10=]!~/\([0-9]+,[0-9]+,[0-9]+\)/){print ;next}{split(,f1,/[(),]/);split(,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([=11=]!~/\([0-9]+,[0-9]+,[0-9]+\)/){
    print ;next}
{split(,f1,/[(),]/);split(,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
.
.