awk/sed:如果任何字段与模式匹配,则替换所有字段

Hil*_*ill 4 unix awk replace sed

我有一个制表符分隔的文件,其中至少有16列(但可能更多),其中第一列是唯一标识符; 和> 10,000行(示例中仅显示6x6),如下所示:

ID  VAR1  VAR2  VAR3  VAR4  VAR5
1    1    1     1     1     1
2    -9   -9    -9    -9    -9
3    3    3     3     3     3
4    4    4     4     -9    4
5    5    5     5     5     5
6    6    -9    6     6     6
Run Code Online (Sandbox Code Playgroud)

如果其中一个值已经是"-9",我需要将VAR1-5的所有值更改为"-9"

所以,期望的输出将是:

ID  VAR1  VAR2  VAR3  VAR4  VAR5
1    1    1     1     1     1
2    -9   -9    -9    -9    -9
3    3    3     3     3     3
4    -9   -9    -9    -9    -9
5    5    5     5     5     5
6    -9   -9    -9    -9    -9
Run Code Online (Sandbox Code Playgroud)

到目前为止,我已经尝试过像这样的awk:

awk -F'\t' '
BEGIN{OFS="\t"}
{for(i=2;i<=NF;i++){if ($i=="-9"){for(j=2;j<=NF;j++){$j="-9"};continue}}};1
' < file1.tab
Run Code Online (Sandbox Code Playgroud)

哪个适用,但在应用于实际数据集时非常慢.有更快的方法吗?也许是grepsed?结合的东西?

tri*_*eee 5

这是一个不会对列数进行硬编码的变体.

awk -F '\t' '/(^|\t)-9(\t|$)/ {
    printf $1; for(i=2; i<=NF; ++i) printf "\t-9"; printf "\n"
    next }
  1' file1 file2
Run Code Online (Sandbox Code Playgroud)

这里的主要优化是Awk立即扫描整行并立即触发正则表达式,而不需要遍历所有字段,除非它已经知道存在匹配.

因为我们知道除了第一个字段之外我们将丢弃所有字段,所以不需要让Awk替换字段以便它们可以打印它们.只需生成我们想要打印的输出并继续前进,而无需触及Awk的内部线条表示.这也应该购买几个周期,尽管这是一个非常小的性能改进.