我一直在尝试在 Shell 脚本中实现一个功能,但不知何故陷入实现困境,需要帮助。
Sample File - f1.txt
col1|col2|col3|rev|spt
A1|54|tyre|56.89|45.23
B1|54|pole|11.89|85.23
C1|54|ture|112.89|185.23
文件可以有任意数量的列,并且不是固定的。我想要实现的是 ->
Concatenate all the Columns in the File (Note- It can have any number of Columns) except the Columns- rev and spt
Whenever it Finds Column Name as rev or spot it shouldnot include in Concatenation.
Example-
Output-
KeyCol|rev|spot
A1~54~tyre|56.89|45.23
B1~54~pole|11.89|85.23
C1~54~ture|112.89|185.23
因此,理想情况下,我想在任何具有任意数量列(除了名为 rev 和 Spot 的列)的文件中创建一个 Composite。
请帮忙
答案1
awk
您可以使用以下命令:
awk -F'|' 'NR==1 {OFS=FS; print "KeyCol", $(NF-1), $NF} NR > 1 {OFS="~"; LAST=$(NF-1) FS $NF; NF-=2; print $0 FS LAST}'
解释
-F '|'
表示输入字段分隔符是|
。NR==1
表示仅操作第一行。在第一行,仅打印第一个字段的“KeyCol”,然后打印最后两个字段,并且OFS
(输出字段分隔符)将是FS
(输入字段分隔符),在您的情况下为|
。- 在第一行 ( ) 之后的下一行
NR > 1
:OFS="~"
意味着新的输出字段分隔符将为~
。LAST=$(NF-1) FS $NF
- 将最后两个字段保存在名为 的字符串变量中LAST
,并用FS
(输入字段分隔符)分隔它们。NF-=2
- 将字段数 (NF
) 减少 2 以排除最后两个字段。print $0 FS LAST
$0
现在仅保留第一个 (NF-2) 字段。- 它将打印它们,并用
OFS
(在本例中,~
- 接下来是原文
FS
(即|
) - 变量 LAST 保存最后两个字段。
输出
awk -F'|' 'NR==1 {OFS=FS; print "KeyCol", $(NF-1), $NF} NR > 1 {OFS="~"; LAST=$(NF-1) FS $NF; NF-=2; print $0 FS LAST}' f1.txt
KeyCol|rev|spt
A1~54~tyre|56.89|45.23
B1~54~pole|11.89|85.23
C1~54~ture|112.89|185.23
注1
您可以将该OFS="~"
行移动到行尾NR==1
,因为这样它将应用于所有接下来的记录,并且您不需要为每一行设置它。
awk -F'|' 'NR==1 {OFS=FS; print "KeyCol", $(NF-1), $NF; OFS="~"} NR > 1 {LAST=$(NF-1) FS $NF; NF-=2; print $0 FS LAST}'
笔记2
您可以创建一个 awk 脚本来自动化它。
$ cat composite.awk
BEGIN { FS = "|" }
NR == 1 {
OFS=FS
print "KeyCol", $(NF-1), $NF
OFS="~"
}
NR > 1 {
LAST=$(NF-1) FS $NF
NF-=2
print $0 FS LAST
}
请注意,我添加了一个BEGIN
设置 的部分FS
,因此您不需要命令-F '|'
的参数awk
。
然后使用脚本文件运行它。
$ awk -f composite.awk f1.txt
KeyCol|rev|spt
A1~54~tyre|56.89|45.23
B1~54~pole|11.89|85.23
C1~54~ture|112.89|185.23