![awk:如果给定行和列上的字符与第一行中同一给定列上的字符不匹配,则替换该字符](https://linux22.com/image/169929/awk%EF%BC%9A%E5%A6%82%E6%9E%9C%E7%BB%99%E5%AE%9A%E8%A1%8C%E5%92%8C%E5%88%97%E4%B8%8A%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%8E%E7%AC%AC%E4%B8%80%E8%A1%8C%E4%B8%AD%E5%90%8C%E4%B8%80%E7%BB%99%E5%AE%9A%E5%88%97%E4%B8%8A%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%8D%E5%8C%B9%E9%85%8D%EF%BC%8C%E5%88%99%E6%9B%BF%E6%8D%A2%E8%AF%A5%E5%AD%97%E7%AC%A6.png)
我已经尝试了很多年,但还没有接近。使用 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