如何跳过文件中修改的第一个,最后一个非空行和空行?

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



如何跳过第一个和最后一个非空行进行更改?我也想跳过空行。

αғs*_*нιη 5

在这里,您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)