【问题标题】:Find and replace values in colum in File A, based on Find/Replace criteria in FileB根据文件中的查找/替换条件查找和替换文件 A 中的列中的值
【发布时间】:2019-01-23 13:45:02
【问题描述】:

我有两个文件。第一个是FileA,它由三列组成(制表符分隔),见下面的内容

文件A

House1   dog    blue
House2   cat    yellow
House3   bird   red
House4   cow   orange
House5   duck   black 
House6   cow    brown

第二个是 FileB,包含两列(制表符分隔) FileB 第 1 列包含 FileA 第 2 列中所有唯一值的列表。 FileB 第 2 列包含我希望它们在第 1 列中的对应值的值列表在 FileA 中替换为

文件B

dog     1
cat     2
cow     3
duck    4
bird    5 

换句话说,我希望找到 FileA 第 2 列中与 FileB 第 1 列匹配的所有值,并将它们替换为 File B 第 2 列中的相应值,并将新的 FileA 输出到新文件(“FileA2” )

新 FileA (FileA2) 的输出应如下所示(即名称第 2 列已全部更改为数字,每个更改对应于 FileB 中的查找替换条件)

House1   1  blue
House2   2  yellow
House3   5   red
House4   3  orange
House5   4   black 
House6   3   brown

是否有任何 awk、grep 或 sed 单行程序可以做到这一点?

注意:在现实生活中,我的“FileA”在第 2 列中有超过 800,000 行和超过 4000 个唯一值,因此最好通过我的 Linux 终端执行此操作。

另外,为了将来参考,是否有任何单行方法可以从给定文件的单个列中提取唯一值列表?

提前感谢您的热心帮助。

【问题讨论】:

  • 您会发现很少有人会为您编写任何代码。当您提出问题和一些说明问题的代码时,此站点效果最佳。我们鼓励您对如何使用最适合您的任何工具转换这些数据进行一些研究。见How to Ask
  • 哪种语言?

标签: awk replace find


【解决方案1】:

以下应该可以解决问题 (bash):

#!/usr/bin/env bash

join -t $'\t' \
    <(sort -t $'\t' -k 2 FileA) \
    <(sort -t $'\t' -k 1 FileB) \
    -1 2 \
    -2 1 | \
sort -t $'\t' -k 2 | \
awk -F '\t' 'BEGIN { OFS="\t" } {print $2, $4, $3}'

说明

首先需要对文件进行排序才能使用join命令:

sort -t $'\t' -k 2 FileA
sort -t $'\t' -k 1 FileB

在这里,我们根据第 2 列 (-k 2) 对 FileA 进行排序,根据第 1 列 (-k 1) 对 FileB 进行排序。制表符用于两个文件作为分隔符 (-t $'\t')。

注意:可以在准备步骤中对输入进行排序(将排序结果存储在临时文件中)以避免每次执行整个命令时重新排序文件。

接下来,join 命令将作为参数:

  • 分隔符 (-t $'\t')
  • 排序后的输入(使用&lt;(sort ...)
  • 用于连接的列:
    • -1 2 = 第一个文件,第二列
    • -2 1 = 第二个文件,第一列

加入后,为了获得您需要的输出(根据输入的第二列排序,包含House 的列),我们需要通过运行sort -t $'\t' -k 2 对上一个命令的输出进行排序。

最后,awk 用于获取仅需要的列(第 2 列、第 4 列和第 3 列,按此顺序),由\t 分隔(BEGIN { OFS="\t" })。

测试

此命令在 Linux 主机上进行了测试。您可以在与 Docker 相同的环境中测试此命令;在您的当前目录中,您必须有FileAFileBjoin.sh,这是一个包含第一个命令的可执行脚本。

跑步:

docker run --rm -v $(pwd):/tmp -w /tmp debian:buster ./join.sh

返回:

House1  1       blue
House2  2       yellow
House3  5       red
House4  3       orange
House5  4       black
House6  3       brown

【讨论】:

  • 您好 norbjd 非常感谢您的回答和解释。我已经尝试过了,但似乎没有任何反应。我已经澄清了我的问题,现在我意识到其中一些可能不清楚,对此感到抱歉。
  • @user10234826 刚刚检查了命令,它可以在我的主机(Linux)上使用您提供的文件(FileAFileB)。也许您的主机上有 BSD 命令行工具(例如在 MacOS 上)而不是 GNU 工具(Linux)?我正在考虑这个问题,因为我已经预料到类似的问题(bash 脚本在 Linux 上工作但在 MacOS 上不工作)。无论如何,我已经编辑了我的答案并给了你一个例子(感谢 Docker)来向你展示它在 Linux 主机上的工作。您可以尝试一点一点地运行命令(首先是join,然后是sort,然后是awk),看看您的机器上哪个部分的命令失败了?
猜你喜欢
  • 2018-02-14
  • 1970-01-01
  • 2017-08-07
  • 2011-07-18
  • 2021-11-06
  • 1970-01-01
  • 1970-01-01
  • 2020-07-29
相关资源
最近更新 更多