ser*_*sat 3 sed awk shell-script text-processing
我有一个类似这样的文件:
H|ACCT|XEC|1|TEMP|20130215035845 849002|48|1208004|100|||1 849007|28|1208004|100|||1 T|2|3
请注意,文件末尾有额外的空行。
我想在所有行中用第 4 列的值替换第 5 列的值,除了第一行和最后一行非空行。
我不能依赖字段的数量,因为最后一行的字段可能与其他字段一样多,而且要修改的行也总是以数字开头。
我试过下面的代码:
awk 'BEGIN{FS="|"; OFS="|"} {$5=$4; print}' in.txt
Run Code Online (Sandbox Code Playgroud)
输出是:
H|ACCT|XEC|1|1|20130215035845
||||
849002|48|1208004|100|100||1
||||
849007|28|1208004|100|100||1
||||
T|2|3||
||||
||||
||||
Run Code Online (Sandbox Code Playgroud)
预期输出:
H|ACCT|XEC|1|TEMP|20130215035845| 849002|48|1208004|100|100||1 849007|28|1208004|100|100||1 T|2|3
如何跳过第一个和最后一个非空行进行更改?我也想跳过空行。
在这里,您awk只使用和处理文件一次。
awk -F'|' 'NR==1{print;next} m && NF{print m}
NF{l="\n"$0; $5=$4; m="\n"$0; c=0}; !NF{c++}
END{ print l; for (; i++<c;)print }' OFS='|' infile
Run Code Online (Sandbox Code Playgroud)
解释:
在这里,我们在第一行用第4个字段的值替换第5个字段的值,然后打印它并执行next。
...如果它(当前下一行)不是空行(至少包含一个字段NF),然后备份整行并\n添加一个ewlinel="\n"$0首先下一个设置第5个字段的值和第4个字段的值$5=$4,最后将其设置为添加m了\newline的变量m="\n"$0;;有一个c变量作为计数器标志,!NF{c++}如果没有看到至少一个字段的行,则用于确定空行的数量;否则c=0将重置此计数器。
现在我们已经修改了m变量中的行,并将m && NF{print m}在下一步awk运行和m设置的位置打印它,并且它不在空行上& NF(这用于防止在空行时打印重复)。
最后,我们将打印每次在执行替换之前备份的未触及的最后一行,END{ print l; ...然后打印从未见过带有循环字段的行的空行数for (; i++<c;)print }'。
如果您不需要多余的空行,那会更短。
awk -F'|' 'NR==1{print;next} m && NF{print m}
NF{l=$0; $5=$4; m=$0} END{ print l}' OFS='|' infile
Run Code Online (Sandbox Code Playgroud)