这是一个 sed 解决方案,如果只是为了说明它在 awk 中是多么容易(并且因为编写 sed 命令很有趣):
$ sed '1b;:a;s/^\([^,]*\),\([^;]*\);/\1,\2\n\1,/;ta' infile
column1,column2
value1,string1
value1,string2
value1,string3
value1,string4
value2,string11
value2,string22
这是基于观察到,在每一行(第一行之后),; 必须用换行符、第一个单词和逗号替换。
用 cmets 可读:
1b # On first line: jump to end and print
:loop # Label to jump to
s/^\([^,]*\),\([^;]*\);/\1,\2\n\1,/ # Substitute one ";" as described above
t loop # If the pattern was modified, jump to "loop"
替换命令中的捕获组是“从行首开始的,以外的字符”(第一组)和“,和第一个;之间的;以外的字符”,所以在循环要更改的第一行时,第一个捕获组始终为value1,第二个捕获组在每次迭代中为string1、string2 等等。
BSD sed,例如在 MacOS 中发现的,抱怨单行中的分支标签。在这种情况下,命令必须像这样分解:
sed -e '1b;:a' -e's/^\([^,]*\),\([^;]*\);/\1,\2\n\1,/;ta' infile