我有一个文件,其中的记录(行)具有两种类型的字段分隔符|
,!
如下所示:
Name|Age|Physics|Chemistry|Maths|English|Batch!Year!AdmisnNo!Grade!Score
Student1|81|65|70|80|88|EWS!2021!1001!A!75
Student2|72|63|60|50|75|EWS!2021!1002!A!85
Student3|72|63|60|50|75|EWS!2021!1002!A!85
如何合并下面给出的Batch
,Year
和AdmisnNo
字段?
请注意,为了简洁起见,我显示了一小部分有用字段,而我的真实文件有许多此类相关字段。我想要删除两个或三个!
标记的该字段不是最后一个,可以是 49 左右字段总数中的任何字段(6 或 7)。
Name|Age|Physics|Chemistry|Maths|English|BatchYearAdmisnNo!Grade!Score
Student1|81|65|70|80|88|EWS20211001!A!75
Student2|72|63|60|50|75|EWS20211002!A!85
Student3|72|63|60|50|75|EWS20211002!A!85
我请求了awk
,但是任何合理的标准命令都是受欢迎的。
答案1
$ awk -F '|' 'BEGIN { OFS = FS } { sub("!", "", $NF); sub("!", "", $NF) }; 1' file
Name|Age|Physics|Chemistry|Maths|English|BatchYearAdmisnNo!Grade!Score
Student1|81|65|70|80|88|EWS20211001!A!75
Student2|72|63|60|50|75|EWS20211002!A!85
Student3|72|63|60|50|75|EWS20211002!A!85
这用于从输入的最后一个分隔字段中awk
删除前两个字符。!
|
NF
在代码中使用任意数字代替awk
可以影响除最后一个字段之外的其他字段。
假设只有最后一个字段包含!
字符,使用sed
:
$ sed -e 's/!//' -e 's///' file
Name|Age|Physics|Chemistry|Maths|English|BatchYearAdmisnNo!Grade!Score
Student1|81|65|70|80|88|EWS20211001!A!75
Student2|72|63|60|50|75|EWS20211002!A!85
Student3|72|63|60|50|75|EWS20211002!A!85
!
这将删除每行的第一个。然后它第二次执行完全相同的替换,!
同时删除第二次。
!
反转每行并连续两次删除第三行,然后再次反转生成的行。这允许其他|
- 分隔字段也包含!
字符。
$ rev file | sed -e 's/!//3' -e 's///3' | rev
Name|Age|Physics|Chemistry|Maths|English|BatchYearAdmisnNo!Grade!Score
Student1|81|65|70|80|88|EWS20211001!A!75
Student2|72|63|60|50|75|EWS20211002!A!85
Student3|72|63|60|50|75|EWS20211002!A!85
答案2
$ cat in | while read -r line ; do line="${line/\!/}" ; echo "${line/\!/}"; done
Name|Age|Physics|Chemistry|Maths|English|BatchYearAdmisnNo!Grade!Score
Student1|81|65|70|80|88|EWS20211001!A!75
Student2|72|63|60|50|75|EWS20211002!A!85
Student3|72|63|60|50|75|EWS20211002!A!85
答案3
使用 GNU awk 作为第四个参数split()
:
$ awk '{n=split($0,f,/[|!]/,s); s[7]=s[8]=""; for (i=1;i<=n;i++) printf "%s%s", f[i], s[i]; print ""}' file
Name|Age|Physics|Chemistry|Maths|English|BatchYearAdmisnNo!Grade!Score
Student1|81|65|70|80|88|EWS20211001!A!75
Student2|72|63|60|50|75|EWS20211002!A!85
Student3|72|63|60|50|75|EWS20211002!A!85
答案4
此任务非常适合在sed
不拆分字段的情况下将第 7 个字段与下一个字段合并:
sed -E 's/|\|!//7' file
再次运行会将第 7 个(最初是第 8 个)与其下一个合并。完全:
sed -Ee 's/|\|!//7' -Ee 's/|\|!//7' file
或者更短的时间(由 Philippos 建议),因为如果第一次替换,则第二次替换将会发生:
sed -E 's/\||!//7;s///7' file
也-E
用于可移植性,即扩展正则表达式。
输出:
Name|Age|Physics|Chemistry|Maths|English|BatchYearAdmisnNo!Grade!Score
Student1|81|65|70|80|88|EWS20211001!A!75
Student2|72|63|60|50|75|EWS20211002!A!85
Student3|72|63|60|50|75|EWS20211002!A!85
请注意,第一次替换后,第 8 个字段变成了第 7 个字段,因此我们7
再次使用它。这就像做一样sed '' file | sed ''
。
此外,这里的不同字段分隔符也很方便,并且可以调整以合并几乎所有相邻字段。