【问题标题】:bash file substring add/replace inplace in matches onlybash 文件子字符串仅在匹配项中添加/替换
【发布时间】:2019-12-05 07:56:54
【问题描述】:

我有一个带有不同条目的VCF file,我需要根据多个匹配替换(或添加如果不存在)一个子字符串。例如

head file

### OUTPUT:
1   47746672    .   A   G   .   .   pz_name=GHARTxI16uuT15921;qual=2201;
1   47746672    .   C   G   .   .   pz_name=GHARMALFI17uuM12201;qual=1932;status=RE;
1   47746675    .   C   G   .   .   pz_name=GHARIGANI17uuA10531;qual=1541;
1   47746675    .   C   G   .   .   pz_name=GHARTxI16uuT15921;qual=1440;status=AC;
1   47746675    .   C   G   .   .   pz_name=GHARFSGSI17uuC19091;qual=816;
# ...

我需要查看一些条件,以便为变异患者的每个组合仅隔离一条特定的行(两者都可以重复,但它们的组合是唯一的)例如以第 4 行为例:

  • 那个$2 == "47746675" && $3 == "C" && $4 == "G"
  • pz_name=GHARTxI16uuT15921

在这个特定的行中,我需要:

  • 如果不存在请添加status=something;
  • status=<something-else> 替换为status=something(如果存在)

如何在 bash 中使用某种就地替换来完成这一切?可能吗?非常感谢替代性能有效方法的建议!

非常感谢您的任何帮助!

【问题讨论】:

  • "inplace" 编辑只是意味着某些命令(sed、perl、awk、ruby 等)在内部使用临时文件。您可以在命令行上轻松地执行command file > tmp && mv tmp file 并获得相同的结果。所以不要沉迷于“就地”做事,它只是一点点语法糖,没有什么可真正关心的,当然也与性能无关。不清楚您要附加什么 - status=something 但什么是“某物”?
  • 你从哪里得到"status=..."

标签: string bash awk in-place vcf-variant-call-format


【解决方案1】:

这是你想要做的吗?

$ awk '{print $0 (/pz_name=GHARFSGSI17uuC19091/ && !/status=/ ? "status=something;" : "")}' file
1   47746675    .   C   G   .   .   ad_alt=73;ad_ref=65;denovo=NA;dp_bin=50;father_dp_bin=NA;father_gt=NA;filter=PASS;gene_name_correct=STIL;gq=99;gt=het;mother_dp_bin=NA;mother_gt=NA;perc_alt=0.5252;pz_name=GHARMALFI17uuM11471;qual=2201;
1   47746675    .   C   G   .   .   ad_alt=65;ad_ref=57;denovo=NA;dp_bin=50;father_dp_bin=NA;father_gt=NA;filter=PASS;gene_name_correct=STIL;gq=99;gt=het;mother_dp_bin=NA;mother_gt=NA;perc_alt=0.5242;pz_name=GHARMALFI17uuM12201;qual=1932;status=RE;
1   47746675    .   C   G   .   .   ad_alt=53;ad_ref=38;denovo=NA;dp_bin=50;father_dp_bin=NA;father_gt=NA;filter=PASS;gene_name_correct=STIL;gq=99;gt=het;mother_dp_bin=NA;mother_gt=NA;perc_alt=0.5824;pz_name=GHARIGANI17uuA10531;qual=1541;
1   47746675    .   C   G   .   .   ad_alt=48;ad_ref=49;denovo=NA;dp_bin=50;father_dp_bin=NA;father_gt=NA;filter=PASS;gene_name_correct=STIL;gq=99;gt=het;mother_dp_bin=NA;mother_gt=NA;perc_alt=0.4948;pz_name=GHARTxI16uuT15921;qual=1440;status=AC;
1   47746675    .   C   G   .   .   ad_alt=29;ad_ref=39;denovo=NA;dp_bin=50;father_dp_bin=NA;father_gt=NA;filter=PASS;gene_name_correct=STIL;gq=99;gt=het;mother_dp_bin=NA;mother_gt=NA;perc_alt=0.4265;pz_name=GHARFSGSI17uuC19091;qual=816;status=something;

如果您想要“就地”编辑,那么使用 GNU awk 使用 awk -i inplace '...' file,或者使用任何 awk 使用 awk '...' file > tmp && mv tmp file

更新:鉴于您更新的问题:

$ awk '$2 == "47746675" && $4 == "C" && $5 == "G" && /pz_name=GHARFSGSI17uuC19091/{ sub(/(status=.*)?$/,"status=something;")} 1' file} 1' file
### OUTPUT:
1   47746672    .   A   G   .   .   pz_name=GHARTxI16uuT15921;qual=2201;
1   47746672    .   C   G   .   .   pz_name=GHARMALFI17uuM12201;qual=1932;status=RE;
1   47746675    .   C   G   .   .   pz_name=GHARIGANI17uuA10531;qual=1541;
1   47746675    .   C   G   .   .   pz_name=GHARTxI16uuT15921;qual=1440;status=AC;
1   47746675    .   C   G   .   .   pz_name=GHARFSGSI17uuC19091;qual=816;status=something;
# ...

【讨论】:

  • @DavidC.Rankin 三元表达式在括号内时总是更容易阅读,并且在某些情况下,在某些 awks 中,未加括号的三元表达式会产生语法错误(我不得不谷歌搜索示例) .所以我总是在我的三元表达式周围使用括号。
  • 谢谢您,但这会将status=something 附加到与pz_name 模式匹配且没有status=... 的所有行中。我只需要在匹配pz_name 和示例if ($2 == "47746675" && $4 == "C" && $5 == "G") 的前三个条件的行中执行此操作。此外,如果status=<something-else> 已经存在,我需要替换(例如用status=something)。抱歉,我知道这是一个非常复杂的解决方法,甚至不知道是否可行.... 再次感谢您
  • 如何添加这些附加条件不是很明显吗?这听起来一点也不复杂,但请清理您的问题以明确您的要求并提供minimal reproducible example,其中包含简洁、可测试的示例输入和预期输出,其中每行不超过 1,200 个字符宽!
  • 是的,好多了,我更新了我的答案。太糟糕了,您没有在示例中包含必须替换现有status= 的情况,因此我们没有进行测试。也太糟糕了,缺少预期的输出,所以确定我的工具产生的输出是否是你想要的。
  • 这正是我所需要的!非常感谢@EdMorton!也感谢您纠正我并教我如何提出更有效的问题!
猜你喜欢
  • 2021-05-01
  • 1970-01-01
  • 2014-08-15
  • 2019-03-17
  • 1970-01-01
  • 2021-03-11
  • 2022-01-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多