如何替换列中的文本

anu*_*rag 7 text-processing regular-expression

我有一个巨大的文件(超过 2 GB),其中的数据如下所示。

12,324,32342,E:fsdsf,23432,34534,45345,324

13,3224,342,E:werwefsdsf,23432,34534,45345,324

121,3244,33442,E:,23432,34534,45345,324
Run Code Online (Sandbox Code Playgroud)

在这里,我需要在遇到E:空格的任何地方替换第 4 列的所有出现"",但在 之后找到字符串的任何地方E:都应保持原样。

预期输出将是:

12,324,32342,E:fsdsf,23432,34534,45345,324

13,3224,342,E:werwefsdsf,23432,34534,45345,324

121,3244,33442,,23432,34534,45345,324
Run Code Online (Sandbox Code Playgroud)

Wil*_*ard 8

你的语法几乎是正确的。要测试 中的字符串是否相等awk,请使用双等号:==。要分配值,请使用单个等号。

所以使用if ($4 == "E:"),你应该得到你想要的结果。

完整的命令看起来像这样。请注意,与您使用的命令只有一个字符不同;那是你唯一的错误:

awk -F , '{ if ($4 == "E:") $4="";}1' OFS=, data.final
Run Code Online (Sandbox Code Playgroud)

为了显示一些不同的语法和不同的方法,以下版本完全等效:

awk -F, -v OFS=, '$4 == "E:" { $4 = "" }; 1' data.final

awk 'BEGIN { FS=OFS="," }; $4 == "E:" { $4 = "" }; {print}' data.final

awk -F, -v OFS=, '{sub( /^E:$/, "", $4); print}' data.final
Run Code Online (Sandbox Code Playgroud)

关于上述事项的注意事项:

  1. 如果你的整个代码块只是一个 if/then,你可以只使用条件作为代码块的过滤器。因此$4 == "E:" {$4 = ""}完全等同于{if ($4 == "E:") {$4 = ""}}
  2. 将“then”语句包含在代码块中是一种很好的做法,即使只有其中一个,即if ($4 == "E:") {$4 = ""}而不是if ($4 == "E:") $4 = "";
  3. -F设定的值FS-v在使用之前设置任何变量的值awk考虑的第一个文件的第一行。(您可能知道这一点。)您也可以使用BEGIN块来做同样的事情;当您想让awk脚本独立时,值得了解。
  4. 1打印行的原因awk是它是一个总是评估为真的条件(过滤器),并且awk当没有代码块附加到过滤器时的默认操作是 to print $0。所以1本身就等价于1 {print}or1 {print $0}或 just {print}
  5. 在我的最后一个变体中,我使用了一个sub函数来用in替换正则表达式/^E:$/(字符串的开头,字符串E:的结尾)。""$4

由于该sub函数返回已进行的替换次数(1 或 0;用于gsub进行多次替换),您可以通过在sub函数结果中添加 1 来解决此问题,以确保您有一个始终为真的模式无论是否进行替换,都会打印结果行。这是代码高尔夫版本,如果您将其放入脚本中,则不建议初学者使用,然后您将对其进行维护:

awk -F, -v OFS=, 'sub(/^E:$/,"",$4)+1' data.final
Run Code Online (Sandbox Code Playgroud)

:)