通过分隔符分割行

通过分隔符分割行

我有一个以空格分隔的文本文件,例如

text1a text2a id1 text4a text5a
text1b text2b id2 text4b text5b
text1c text2c id3,id4 text4c text5c
text1d text2d id5,id6,id7 text4d,text4di text5d

该文件大约有 150 万行长。

有些行有两个 id,用逗号分隔,例如示例中的第 3 行。当尝试将该文件与另一个文件(其中 id 可能是id3或 )连接时,这会导致问题id4

我想找到第 3 列中存在逗号的所有实例,并将两侧的内容分隔成单独的行,例如上面的文件将变成。

text1a text2a id1 text4a text5a
text1b text2b id2 text4b text5b
text1c text2c id3 text4c text5c
text1c text2c id4 text4c text5c
text1d text2d id5 text4d,text4di text5d
text1d text2d id6 text4d,text4di text5d
text1d text2d id7 text4d,text4di text5d

有些行包含 3 个或更多以逗号分隔的 id。逗号可以出现在其他列中,但它们应该保持原样。顺序并不重要,例如 id3 或 id4 在文件中是否排在第一位。

我对等方面相当缺乏经验awksed我认为这是完成这项工作的最佳工具。

有人能指出我正确的方向吗?

答案1

$ awk 'split($3,f,/,/)>1{for (i=1; i in f; i++) {$3=f[i]; print} next } 1' file
text1a text2a id1 text4a text5a
text1b text2b id2 text4b text5b
text1c text2c id3 text4c text5c
text1c text2c id4 text4c text5c
text1d text2d id5 text4d,text4di text5d
text1d text2d id6 text4d,text4di text5d
text1d text2d id7 text4d,text4di text5d

上面保留了 $3 中列出的 id 的顺序,如果这不合需要,那么您可以for (i in f)代替for (i=1; i in f; i++).

如果 split() 返回大于 1,则仅执行包含分配 $3 的循环的块比无条件执行分配更有效,因为每次分配给字段时,都会强制 awk 重建当前记录,用 OFS 替换所有 FS。

答案2

由于拆分行的顺序并不重要,因此我们可以使用以下命令进行操作awk

$ awk '{ split($3,a,","); for (i in a) { $3 = a[i]; print } }' file
text1a text2a id1 text4a text5a
text1b text2b id2 text4b text5b
text1c text2c id3 text4c text5c
text1c text2c id4 text4c text5c
text1d text2d id5 text4d,text4di text5d
text1d text2d id6 text4d,text4di text5d
text1d text2d id7 text4d,text4di text5d

对于每一行,这会将第三个字段放在逗号上,从而创建数组a。如果字段中没有逗号,则该数组可能只包含单个元素。

然后,代码循环遍历数组的索引a(这可能最终以任何顺序完成,具体取决于您awk实现数组的方式),通过将第三个字段设置为数组中的当前元素来修改第三个字段a,然后打印完整的(可能被修改)记录。

答案3

另一种方法可能是:

cat fun.awk

$3~/^id[0-9]+,/ {
    split($3, store, ",");
    for (i = 1; i in  store; i++)
        print $1, $2, store[i], $4, $5

    next
}

{ print $0 }

如果第三列包含逗号 ( $3~/^id[0-9]+,/),则将其拆分并为每列打印一行,然后转到下一个循环。否则打印整行 ( $0)。

相关内容