awk - 解析字段中具有与定界符相同字符的文本

awk - parse text having same character in fields as delimiter

考虑这个来源:

field1;field2;"data;data field3";field4;"data;data field5";field6
field1;"data;data field2";field3;field4;field5;"data;data field6"

如您所见,字段定界符被用在某些字段中,包含在 " 之间。我不能直接用 awk 解析,因为没有办法避免不必要的分裂,至少我还没有找到办法。此外,这些特殊字段在一行中的位置可变,可以出现一次、两次、四次等

我想到了一个涉及预解析步骤的解决方案,我将这些字段中的 ; 替换为某种代码。问题是 sed / awk 执行贪婪 REGEX 匹配。所以在上面的例子中,我只能在每行用引号括起来的最后一个字段中替换 ;

如何匹配引号的每个实例并替换其中的特定 ;?我不想使用 perlpython

使用 gnu awk 您可以使用特殊的 FPAT 变量为您的字段设置正则表达式。

您可以使用此命令将所有 ; 替换为双引号内的 |

awk -v OFS=';' -v FPAT='"[^"]*"|[^;]*' '{for (i=1; i<=NF; i++) gsub(/;/, "|", $i)} 1' file

field1;field2;"data|data field3";field4;"data|data field5";field6
field1;"data|data field2";field3;field4;field5;"data|data field6"

作为 FPAT 的替代方法,您可以将 awk FS 设置为双引号,然后将分号分隔符换成其他所有字段:

awk -F"\"" '{for(i=1;i<=NF;++i){ if(i%2==0) gsub(/;/, "|", $i)}} {print [=10=]}' yourfile

这里的awk是:

  1. 用双引号分割记录(-F"\"")
  2. 遍历找到的每个字段 ({for(i=1;i<=NF;++i))
  3. 测试字段序号的 mod 2 是否为 0 (if(i%2==0))
  4. 如果是偶数,则用竖线替换分号 (gsub(/;/, "|", $i))
  5. 打印出转换后的记录 ({print [=18=]})