我正在尝试使用模式匹配来格式化自定义数据。我没有得到预期的格式。虽然我不太懂 shell 脚本,但我能够根据来自 SE 的多个来源的引用构建一个脚本。
需要帮助一些建议,请指教。
输入数据:
WWWW PPPA TTTT
XX XY
XA XB
XB XC
XY XE
HHHH PPPA 400 XXX6
WWWW PPPB TTTT
XB XC
XY XE
HHHH PPPB 200 XXX1
WWWW PPPC TTTT
XX XY
XA XB
XB XC
HHHH PPPC 300 XXX9
WWWW PPPA TTTT
XA XB
XB XC
XN XX
HHHH PPPA 300 XXX6
WWWW PPPD TTTT
XX XY
XA XB
XB XC
XY XE
XN XA
HHHH PPPD 500 XXX4
预期输出:
WWWW PPPB TTTT
XX XC
XY XE
HHHH PPPB 200 XXX1
WWWW PPPC TTTT
XX XY
XA XB
XB XC
HHHH PPPC 300 XXX9
WWWW PPPA TTTT
XA XB
XB XC
XN XX
XX XY
XA XB
XB XC
XY XE
HHHH PPPA 700 XXX6
WWWW PPPD TTTT
XX XY
XA XB
XB XC
XY XE
XN XA
HHHH PPPD 500 XXX4
请参阅此处的评论,这也是通过引用其他代码构建的。我自己正在尝试理解这里的逻辑。我对 shell 很基础,希望学习和理解更多。
pattern='PPPA'
awk -v ptn="${pattern}" ' # pass pattern in as awk variable "ptn"
$0 ~ "^WWWW "ptn"$" { save=1 ; next } # start of group => set save flag; skip to next line
$0 ~ "^HHHH "ptn" " { save=0 ; next } # end of group => clear save flag; skip to next line
save { ++i ; line[i]=$0 ; next } # if save=1 then store current line in next position of array line[]; skip to next line
{ print } # otherwise print all other lines to stdout
END { if ( i >= 1 ) # if we found any matches ...
{ printf "%-561s%s", "WWWW", ptn # print the new "WWWW" line
for ( j=1 ; j<=i ; j++ ) # then loop through our list of indices ...
{ print line[j] } # printing the associated line[] element
fmt="HHHH %s %02i\n"
printf "%-69s%-491s%02i" "HHHH", i, ptn # print the "HHHH" line
}
}
' TESTX1.txt
我在这里想要实现的是将两个数据集与匹配模式结合起来。首先搜索模式,如果匹配则WWWW
再搜索模式。PPPA
然后将这个特定数据块的开始和结束记录合并起来。
在输入数据集中,您会看到有 2 组具有WWWW
和PPPA
模式。我想将它们合并为一个数据组,同时也调整结束记录数据计数:
HHHH PPPA 400 XXX6
+ HHHH PPPA 300 XXX6
= HHHH PPPA 700 XXX6 (400 + 300 = 700)
WWWW PPPA TTTT
将保持不变,因为它们对于两个数据组都是相同的。
脚本输出不符合预期:
WWWW PPPA TTTT
XX XY
XA XB
XB XC
XY XE
WWWW PPPB TTTT
XB XC
XY XE
HHHH PPPB 200 XXX1
WWWW PPPC TTTT
XX XY
XA XB
XB XC
HHHH PPPC 300 XXX9
WWWW PPPA TTTT
XA XB
XB XC
XN XX
WWWW PPPD TTTT
XX XY
XA XB
XB XC
XY XE
XN XA
HHHH PPPD 500 XXX4
感谢您提供解决方案,发布数据未被操纵的实际数据。逻辑保持不变,但格式不同。
实际数据输入
WWW PPPA TTTT XXXAAXX
XX XY
XA XB
XB XC
XY XE
HHH 500 PPPA TTTT
WWW PPPB TTTT XXXAAXX
XB XC
XY XE
HHH 3500 PPPB TTTT
WWW PPPA TTTT XXXAAXX
XA XB
XB XC
XN XX
HHH 1000 PPPA TTTT
WWW PPPC TTTT XXXAABB
XX XY
XA XB
XB XC
XY XE
XN XA
HHH 4000 PPPC TTTT
实际数据预期输出#
WWW PPPB TTTT XXXAAXX
XB XC
XY XE
HHH 3500 PPPB TTTT
WWW PPPA TTTT XXXAAXX
XX XY
XA XB
XB XC
XY XE
XA XB
XB XC
XN XX
HHH 1500 PPPA TTTT
WWW PPPC TTTT XXXAABB
XX XY
XA XB
XB XC
XY XE
XN XA
HHH 4000 PPPC TTTT
答案1
您试图匹配开始模式中的行尾$
,但输入中的该位置没有行尾。END
页眉/页脚的块格式也被破坏。
稍微修改一下代码:
pattern='PPPA'
awk -v ptn="$pattern" '
$0 ~ "^WWWW " ptn " "{ save=1; header=$0; next }
save && $0 ~ "^HHHH " ptn " "{ save=0; footer=$0; sum+=$3; next }
save{ line[i++]=$0; next }
1 # print current record
END{
if (i){
print header
for (j=0;j<i;j++) print line[j]
$0=footer # assign footer to current record
$3=sum # replace 3rd field with sum
print # print footer
}
}
' file
输出:
WWWW PPPB TTTT
XB XC
XY XE
HHHH PPPB 200 XXX1
WWWW PPPC TTTT
XX XY
XA XB
XB XC
HHHH PPPC 300 XXX9
WWWW PPPD TTTT
XX XY
XA XB
XB XC
XY XE
XN XA
HHHH PPPD 500 XXX4
WWWW PPPA TTTT
XA XB
XB XC
XY XE
XA XB
XB XC
XN XX
HHHH PPPA 700 XXX6
修改后的实际数据代码如下:
- 匹配
WWW
并HHH
作为第一个字段,模式作为第二个(页眉)或第三个(页脚)字段 - 将旧的页脚值保存在 中
oldvalue
,用于在块sum
中替换该值END
- 使用第二个字段作为页脚值 (
sum
,oldvalue
)
pattern='PPPA'
awk -v ptn="$pattern" '
$1=="WWW" && $2==ptn{ save=1; header=$0; next }
save && $1=="HHH" && $3==ptn{ save=0; oldvalue=$2; sum+=$2; footer=$0; next }
save{ line[i++]=$0; next }
1
END{
if (i){
print header
for (j=0;j<i;j++) print line[j]
sub(oldvalue, sum, footer) # replace oldvalue with sum
print footer
}
}
' file
输出:
WWW PPPB TTTT XXXAAXX
XB XC
XY XE
HHH 3500 PPPB TTTT
WWW PPPC TTTT XXXAABB
XX XY
XA XB
XB XC
XY XE
XN XA
HHH 4000 PPPC TTTT
WWW PPPA TTTT XXXAAXX
XX XY
XA XB
XB XC
XY XE
XA XB
XB XC
XN XX
HHH 1500 PPPA TTTT