【问题标题】:Compare every element of two files (row wise)比较两个文件的每个元素(逐行)
【发布时间】:2021-07-17 08:06:30
【问题描述】:

我有三个文件,想在两个文件之间逐行比较每个元素,并想应用条件语句。

file1 示例

Aa 1.3
Ca 1.1
Ba 0.8
Da 0.65
Fa 0.63
Ea 0.6
Za 0.4
Ha 0.1

文件 2 示例

Ca Ba Da Fa Ea Za Ha
Aa Ca Ba Da Fa Ea

文件 3 示例

Fa Ca Za
Ha Ca Ba Da

现在我想逐行比较 file2 和 file3 的元素。如果 file2 的特定行的元素存在于文件 3 的同一行中,则执行其他任务。

我试过了,但没有成功

NG=`cat file1 | awk 'END{print NR}'`

awk -v N="$NG" '
FNR==NR{
 a[$0]=$0
 next
}
{
 for(i=1;i<=NF;i++){
   if($i in a){
   print sqrt((N-M)/M)
  }
 else
 {
  print -sqrt(M/(N-M))
 }}
}' file2 file3 

其中 N 是 file1 中的行数,M 是 file3 特定行中的字段数。文件2 所以我预期的输出文件就像

 1.29099 -0.774597 -0.774597 1.29099 -0.774597 1.29099 -0.774597
 -1 1 1 1 -1 -1

【问题讨论】:

  • 您将整行存储到数组中,但按单个字段查找。对于给定的输入,$i in a 总是会失败。
  • 在预期输出中,第 1 行的第 4 个值应该是 2?
  • file1 与手头的任务有什么关系? N 可能只是一些数字;它来自哪里似乎并不特别重要。
  • 没错,对文件的处理没有任何意义。只是一个用于计算的值。
  • @EdMorton 我按照建议对预期输出进行了更改

标签: python-3.x shell awk


【解决方案1】:

你可以试试下面awk脚本。

awk -v N="$(wc -l < file1)" '{for (i=1;i<=NF;i++) {arr[$i]}; M=NF; getline<"file2"; for (i=1; i<=NF; i++){if ($i in arr){printf "%f ", sqrt((N-M)/M)} else{printf "%f ", -sqrt(M/(N-M))}}; delete arr; print ""}' file3

扩展版:

awk -v N="$(wc -l < file1)" '{
    for (i=1;i<=NF; i++) {
        arr[$i]
    }
    M = NF
    getline < "file2"
    for (i = 1; i <= NF; i++) {
        if ($i in arr) {
            printf "%f ", sqrt((N - M) / M)
        } else {
            printf "%f ", -sqrt(M / (N - M))
        }
    }
    delete arr
    print ""
}' file3

【讨论】:

  • 输出的第一行是完美的。但根据示例,file2 的第 2 行中的 5 值不存在于第 3 个文件的第 2 行中。所以输出应该是负数。但它给出了积极的价值。同样,它发生在所有其他行
  • 在目前的情况下,它搜索整个文件3而不是特定的行
  • @RaviSaroch 我已经更新了答案,请立即尝试。
  • 请参阅awk.freeshell.org/AllAboutGetline了解何时以及如何致电getline
【解决方案2】:

从您问题中的文字看来,这可能是您正在尝试做的事情:

$ cat tst.awk
FILENAME == ARGV[1] {
    n = FNR
}
FILENAME == ARGV[2] {
    for (i=1; i<=NF; i++) {
        keys[FNR,$i]
    }
    presVals[FNR] = sqrt( (n - NF) / NF )
    abstVals[FNR] = -sqrt( NF / (n - NF) )
}
FILENAME == ARGV[3] {
    for (i=1; i<=NF; i++) {
        val = ( (FNR,$i) in keys ? presVals[FNR] : abstVals[FNR] )
        printf "%s%s", val, (i<NF ? OFS : ORS)
    }
}

$ awk -f tst.awk file1 file3 file2
1.29099 -0.774597 -0.774597 1.29099 -0.774597 1.29099 -0.774597
-1 1 1 1 -1 -1

但您的预期输出似乎与您的示例输入不匹配,所以如果那是您真正想要的,请确认。

不要使用全大写的变量名称,例如 NM,以避免与内置变量发生冲突,并让代码看起来像是在使用内置变量t.

【讨论】:

  • 这看起来更精致!!很好的解决方案?
猜你喜欢
  • 2015-12-02
  • 2014-08-24
  • 2018-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多