awk:如果给定行和列上的字符与第一行中同一给定列上的字符不匹配,则替换该字符

awk:如果给定行和列上的字符与第一行中同一给定列上的字符不匹配,则替换该字符

我已经尝试了很多年,但还没有接近。使用 awk,如何:将每列中每行 > 1 上的每个 '*' 替换为 '-',但前提是第 1 行中的相应列不是 '*'?

输入示例:
a|s|d|f|g|*|A|*|*|g|c|a|*|A|*
a|*|*|f|g|*|*|*|*|g|c|a|*|A|*
*|s|*|f|g|*|a|t|*|g|c|a|*|A|*
a|s|d|*|g|*|T|*|C|g|c|a|a|A|T

输出示例
a|s|d|f|g|*|A|*|*|g|c|a|*|A|*
a|-|-|f|g|*|-|*|*|g|c|a|*|A|*
-|s|-|f|g|*|a|t|*|g|c|a|*|A|*
a|s|d|-|g|*|T|*|C|g|c|a|a|A|T

答案1

需要扫描标题行以查找所有“not *”。
列“没有”*可以存储在数组中a[]
对于所有下一行,仅存在于a[] 可能需要改变。

这可以实现为:

awk -F'|' 'BEGIN{OFS=FS}
           NR==1 {
                   for(i=1;i<=NF;i++) if( $i != "*" ) a[i]
                 } 
           NR>1  {
                   for(i in a)        if( $i == "*" ) $i="-"
                 } 
           1
          ' file

a|s|d|f|g|*|A|*|*|g|c|a|*|A|*
a|-|-|f|g|*|-|*|*|g|c|a|*|A|*
-|s|-|f|g|*|a|t|*|g|c|a|*|A|*
a|s|d|-|g|*|T|*|C|g|c|a|a|A|T

这实现了所需的最少更改。应该是最快的。

答案2

一种可能的方法(可能不是最好的)

awk -F'|' '
  BEGIN{OFS=FS} 
  NR==1 {
    for(i=1;i<=NF;i++) if($i=="*") a[i]
  } 
  {
    for(i=1;i<=NF;i++) if($i=="*" && !(i in a)) $i="-"
  } 
  1
' file
a|s|d|f|g|*|A|*|*|g|c|a|*|A|*
a|-|-|f|g|*|-|*|*|g|c|a|*|A|*
-|s|-|f|g|*|a|t|*|g|c|a|*|A|*
a|s|d|-|g|*|T|*|C|g|c|a|a|A|T

相关内容