【问题标题】:Linux/Bash: replace if the same id in tableLinux/Bash:如果表中的 id 相同,则替换
【发布时间】:2018-11-20 16:55:20
【问题描述】:

我有两个文件:

file 1
Name   Height
Jay    180
Kathy  171
Amy    163
Bill   176
Hellen 157

file 2
Name   Height
Jay    195
Amy    173
Hellen 161

如果名称(第 1 列)在文件 2 中匹配,我想替换文件 1 中第二列的值。如果名称不匹配,则保持不变。结果应该是:

Name   Height
Jay    195
Kathy  171
Amy    173
Bill   176
Hellen 161

只有 Jay、Amy 和 Hellen 的身高发生了变化,因为他们的名字存在于文件 2 中。

我尝试使用 for 循环加上 awk 或 join 来解决这个问题,但效果不是很好。最后我使用excel从文件2生成了一个LONG awk命令并应用了离子文件1,它起作用了:

awk '{OFS="\t";
if($1~/^Jay$/){$2="195"; print $0;} 
else if($1~/^Amy$/){$2="173"; print $0;} 
else if($1~/^Hellen$/){$2="161"; print $0;} 
}' file 1

这样,我尝试用for循环来生成:

else if($1~/^   Amy   $/){$2="   173    ";print $0;}  

上面包含命令 part1 & name & command part2 & height to replace & command part3。但是很难将这些命令放入变量中,因为它包含特殊字符,例如:if、~、/、$

我想知道是否有任何更简单的方法可以仅通过命令来完成? 谢谢!

查理

【问题讨论】:

  • 订单相关吗?如果不是,您可以只使用文件 2,并添加文件 1 中不在文件 2 中的记录。如果顺序很重要,请说明其意义,因为这些似乎不是按字母顺序排列的。
  • @Charlie,通过查看您的个人资料了解到您几乎没有选择任何答案作为正确答案,请尝试从所有答案中选择一个答案作为正确答案,并更新所有用户他们的解决方案发生了什么。你也可以看到这个链接一次stackoverflow.com/help/someone-answers

标签: bash join awk


【解决方案1】:

如果顺序不重要,可以很简单

$ awk '!a[$1]++' file2 file1

Name   Height
Jay    195
Amy    173
Hellen 161
Kathy  171
Bill   176

【讨论】:

  • 这太棒了。请您详细说明它的工作原理吗?
  • ! 测试我们是否看过记录。如果测试为真,它会打印。作为测试它的事后副产品,++ 递增密钥,以便下次我们看到$1(名称)时,它会被看到,所以它不会再次打印。这就是他在file1 之前列出file2 的原因。 file2 中的任何内容优先,然后从 file1 打印 file2 中不在 中的任何内容。这是一个非常优雅的解决方案。
  • @PaulHodges,正确。我应该添加的另一件事是它假定每个文件中的唯一键,因为重复将被忽略。但在这个问题中,它是隐含的。
  • 感谢您的澄清!
【解决方案2】:

请您尝试关注一下。

awk 'FNR==NR{a[$1]=$2;next} {$0=a[$1]?$1 OFS a[$1]:$0} 1'  file2  file1 | column -t

输出如下。

Name    Height
Jay     195
Kathy   171
Amy     173
Bill    176
Hellen  161

【讨论】:

    【解决方案3】:

    这个脚本也可以。

    #!/bin/bash
    
    while read name height
    do
            printed=0
            printf "$name\t"
            while read subname subheight
            do
                    [[ $name == $subname ]] && printf "$subheight\n" && printed=1
                    continue
            done <<< "$( tail -n +2 secondary.txt)"
            [[ $printed -eq 0 ]] && printf "$height\n"
    
    done <<< "$( tail -n +2 main.txt)"
    

    【讨论】:

      猜你喜欢
      • 2021-12-18
      • 1970-01-01
      • 2016-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-23
      • 1970-01-01
      相关资源
      最近更新 更多