使用shell将标题移动为细节的一部分

时间:2014-12-17 03:45:28

标签: shell sed

我有一个输入文件,我需要转换为DB友好。

原件:

H|cust_id|order_no
D|itemcode|itemdesc
D|itemcode|itemdesc

期望的输出:

itemcode|itemdesc|cust_id|order_no
itemcode|itemdesc|cust_id|order_no

我正在阅读sed,但无法理解。

2 个答案:

答案 0 :(得分:3)

awksed

更容易
awk -F'|' '$1=="H" { c=$2; o=$3 } $1=="D" { printf("%s|%s%|%s|%s\n", $2, $3, c, o) }'

如果必须在sed中完成,则保留空间是关键。在文件script.sed中:

sed -e '/^H|/{ s/^H|//; h; d; }' \
    -e '/^D|/{ s/^D|//; G; s/\n/|/; }'

第一行与H行匹配,删除H|,并保存保留空间中剩余的内容,并删除该行以防止打印任何内容。

第二行匹配D行,删除D|,将换行符和保留空间的内容附加到模式空间,用管道替换换行符,并打印结果

给定输入文件data

H|cust_id-1|order_no-11
D|itemcode-1|itemdesc-1
D|itemcode-2|itemdesc-2
H|cust_id-2|order_no-22
D|itemcode-3|itemdesc-3
D|itemcode-4|itemdesc-4

示例输出:

$ awk -F '|' '$1 == "H" { c=$2; o=$3 } $1 == "D" { printf("%s|%s%|%s|%s\n", $2, $3, c, o) }' data
itemcode-1|itemdesc-1|cust_id-1|order_no-11
itemcode-2|itemdesc-2|cust_id-1|order_no-11
itemcode-3|itemdesc-3|cust_id-2|order_no-22
itemcode-4|itemdesc-4|cust_id-2|order_no-22
$ sed -e '/^H|/{ s/^H|//; h; d; }' -e '/^D|/{ s/^D|//; G; s/\n/|/; }' data
itemcode-1|itemdesc-1|cust_id-1|order_no-11
itemcode-2|itemdesc-2|cust_id-1|order_no-11
itemcode-3|itemdesc-3|cust_id-2|order_no-22
itemcode-4|itemdesc-4|cust_id-2|order_no-22
$

答案 1 :(得分:0)

使用两个 sed命令(假设输入文件file),这是一个可能更容易理解的解决方案:

# Extract header values from the 1st line, dropping the 1st column.
headerValues=$(sed -E '1 s/[^|]*\|//; q' file)

# Append header values to all subsequent lines, dropping the 1st column.
sed -En '2,$ s/[^|]*\|(.*)/\1|'"$headerValues"'/p' file

# Additional requirement, added later by the OP:
# Store the first header value separately in shell variable $firstHeaderValue.
IFS='|' read -r firstHeaderValue rest <<<"$headerValues"

注意:

  • 假设每个文件只有一个标题行,必须是第一行,后面是明细行。
  • 不对列的宽度或数量做任何假设。
  • sed命令应该适用于Linux和OSX / FreeBSD。