【问题标题】:Output field separators in awk after substitution in fields在字段中替换后在 awk 中输出字段分隔符
【发布时间】:2016-11-06 12:27:14
【问题描述】:

是否总是这样,在修改awk 中的特定字段后,输出字段分隔符上的信息会丢失?如果有多个字段分隔符并且我希望恢复它们会怎样?

例如,假设我有一个简单的文件example,其中包含:

a:e:i:o:u

如果我只是运行一个awk 脚本,它会考虑输入字段分隔符,它会打印我文件中的每一行,例如运行

awk -F: '{print $0}' example

我会看到原来的行。但是,如果我直接修改其中一个字段,例如与

awk -F: '{$2=$2"!"; print $0}' example

我没有取回原始行的修改版本,而是看到由默认空格分隔符分隔的字段,即:

a e! i o u

我可以通过指定 OFS 来取回原始版本的修改版本,例如:

awk -F: 'BEGIN {OFS=":"} {$2=$2"!"; print $0}' example

但是,在存在多个势场分隔符的情况下,但在多个分隔符的情况下,是否有一种简单的方法可以恢复原始分隔符?

例如,如果example:; 作为分隔符,我可以使用-F":|;" 来处理文件,但OFS 不足以恢复它们相对位置的原始分隔符。

更明确地说,如果我们切换到 example2 包含

a:e;i:o;u

我们可以使用

awk -F":|;" 'BEGIN {OFS=":"} {$2=$2"!"; print $0}' example2

(或-F"[:;]")获取

a:e!:i:o:u

但我们已经失去了 : 和 ; 之间的区别如果我们能够恢复,它会一直保持下去

a:e!;i:o;u

【问题讨论】:

  • 这个问题是这里少有的好问题之一。为什么不简单地使用-F'[:;]' 添加一个无效的示例。这将使问题变得完美 - imo
  • 添加了显式示例
  • 与 RT 等效的字段分隔符显然是 GNU 扩展。我想知道他们为什么没有它。
  • @MichaelVehrs 这并不难,只是不必要的时间和内存消耗。预计 awk 将非常高效。如果我们需要为每一行上的每个 FS 存储与 FS 匹配的字符串,它就会为几乎不需要的功能添加循环。当然,您可以添加标志来打开/关闭它,但是字段拆分代码必须检查标志,如果不参考标志,您将无法判断代码的作用。简单地提供一个函数,您可以调用它来做您想做的事情,如果/当您想要它。
  • 此外,由于这是拆分字符串的有用功能,通常您需要split() 函数中提供它,一旦您为split(<any string>,...) 提供它,您就可以将其用于split($0,...),因此没有必要以其他方式专门为$0 复制功能,尤其是考虑到很少需要该功能。

标签: awk


【解决方案1】:

您需要使用 GNU awk 作为第 4 个参数来 split() 来保存分隔符,就像 RT 对 RS 所做的那样:

$ awk -F'[:;]' '{split($0,f,FS,s); $2=$2"!"; r=s[0]; for (i=1;i<=NF;i++) r=r $i s[i]; $0=r} 1' file
a:e!;i:o;u

没有自动填充的 FS 匹配字符串数组,因为每次将记录拆分为字段时,存储与 FS 匹配的字符串会花费时间和内存。相反,GNU awk 人员为 split() 提供了第 4 个参数,因此您可以在需要时自己进行操作。这是几年前在 comp.lang.awk 新闻组中,有经验的 awk 用户和 gawk 提供者之间进行了长时间对话的结果,然后大家都同意这是最好的方法。

请参阅split()https://www.gnu.org/software/gawk/manual/gawk.html#String-Functions

【讨论】:

    猜你喜欢
    • 2014-01-17
    • 2014-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多