awk 命令来分隔第二列

awk 命令来分隔第二列

我有一个包含以下格式数据的文件

Item1|keys,books,helmet,handle,
Item2|Bike,
Item3
Item4|Tyre,brakes,headlight,clamps,rollergrip,
Item5|Nails,hammers,

我希望将上面的数据转换为下面的格式

Item1|keys
Item1|books
Item1|helmet
Item1|handle
Item2|Bike
Item3
Item4|Tyre
Item4|brakes
Item4|headlight
Item4|clamps
Item4|rollergrip
Item5|Nails
Item5|hammers

我试图通过使用 cut 命令来实现这一点,尽管工作正常,但我想知道这可以使用 awk 命令来实现。因为如果输入文件大小变得更大,那么它应该会很麻烦。

答案1

sed -e 's/,$//' -e '/^[^|]*$/s/$/|/' file.in |
awk -F'[|,]' -vOFS='|' '{ for (i = 2; i <= NF; ++i) { print $1, $i } }'

对输入数据进行sed一些预处理。它会删除每行末尾的逗号 ( -e 's/,$//'),如果一行不包含管道符号,则会在末尾添加 1 ( -e '/^[^|]*$/s/$/|/')。

示例数据通过过滤器转换为以下内容sed

Item1|keys,books,helmet,handle
Item2|Bike
Item3|
Item4|Tyre,brakes,headlight,clamps,rollergrip
Item5|Nails,hammers

awk脚本接受此信息并将每一行解释为一组由管道符号或逗号 ( -F'[|,]') 分隔的字段。对于每个输入行,它将重复地将第一个字段与其他每个字段配对并输出它们。输出中的每对字段均由管道符号 ( -vOFS='|') 分隔。

结果是

Item1|keys
Item1|books
Item1|helmet
Item1|handle
Item2|Bike
Item3|
Item4|Tyre
Item4|brakes
Item4|headlight
Item4|clamps
Item4|rollergrip
Item5|Nails
Item5|hammers

答案2

awk解决方案:

awk -F'|' 'NF>1 && $2~/[^,]+,[^,]*/{ 
           len=split($2,a,","); 
           for(i=1;i<=len;i++) { 
               if(a[i]!="") print $1,a[i] 
           } 
           next }1' OFS='|' file

输出:

Item1|keys
Item1|books
Item1|helmet
Item1|handle
Item2|Bike
Item3
Item4|Tyre
Item4|brakes
Item4|headlight
Item4|clamps
Item4|rollergrip
Item5|Nails
Item5|hammers

细节

  • -F'|'- 字段分隔符

  • NF>1 && $2~/[^,]+,[^,]*/- 考虑至少 2 个字段,其中第二个字段内的值以逗号分隔

  • len=split($2,a,",")a-通过分隔符将第二个字段拆分为数组,。该len变量分配有数组大小(块数)

  • for(i=1;i<=len;i++) 迭代通过“

  • if(a[i]!="") print $1,a[i]- 打印除空值之外的每个相关序列

答案3

另一个awk版本

  • 将字段分隔符设置为|,
  • 如果记录的字段少于 2 个,则按原样打印
  • else 循环遍历所有字段 2 来NF-1打印$1and (这会跳过由尾随逗号引起的$i$NF

IE

$ awk 'NF<2 ; {for (i=2;i<NF;i++) print $1,$i}' FS='[|,]' OFS='|' file
Item1|keys
Item1|books
Item1|helmet
Item1|handle
Item2|Bike
Item3
Item4|Tyre
Item4|brakes
Item4|headlight
Item4|clamps
Item4|rollergrip
Item5|Nails
Item5|hammers

相关内容