我有以下bash
/awk
脚本,它可以执行我想要的操作,只是它添加了一个我不知道其含义的控制符号。
#!/usr/bin/env bash
# Merge two cross section files from Resummino
file1=filein1
file2=filein2
fileout=fileout
awk '{
xs_nlo[$1," ",$2] += $4
xs_lo[$1," ",$2] += $3
}
END {
for (xs in xs_nlo){
print(xs, xs_lo[xs], xs_nlo[xs])
}
}
' "${file1}" "${file2}"
可能的内容filein1
:
100.000 500.000 7.878892e+00 1.027803e+01
100.000 1000.000 9.667085e+00 1.274467e+01
100.000 2000.000 1.029358e+01 1.361803e+01
100.000 5000.000 1.049836e+01 1.390297e+01
100.000 10000.000 1.052944e+01 1.394593e+01
与 类似filein2
,只是每行的最后两个值不同。该awk
脚本应该将每行中的第三个值相加,假设第一个和第二个值相同。第四个值也是如此。
输出文件应该与输入文件具有相同的结构。在控制台中,输出文件看起来相同,但是在 中打开它vim
,我看到一个不容易搜索的控制字符:
100.000^\ ^\300.000 3.42 4.57283
这是什么^\ ^\
意思?我怎样才能摆脱它?
答案1
问题的根源在于分隔符$1," ",$2
。
来自文档:
awk 通过将索引串联成一个字符串来支持多维数组。 awk 将索引转换为字符串(请参阅转换)并将它们连接在一起,并在它们之间使用分隔符。这将创建一个描述单独索引值的单个字符串。组合字符串用作普通一维数组的单个索引。使用的分隔符是内置变量的值子集
子集
下标分隔符。它的默认值为“\034" 并用于分隔多维数组的索引部分。因此,表达式 'foo["A", "B"]' 真正访问 foo["A\034B"]
标准 awk 通过用逗号分隔下标值来模拟多维数组。这些值连接成单个字符串,并由 SUBSEP 的值分隔。
以这种方式创建这样的下标的事实不会被保留;因此,改变子集可能会产生意想不到的后果。
答案2
对于第二部分:
这 ^\ ^\ 是什么意思,我怎样才能摆脱它?
其他一些答案已经解释了其中的逗号(,
)[$1," ",$2]
变成了SUBSEP。 Thta 是字符\034
(八进制)或0x1C
(十六进制)。
该字符也可以用控制编码编写为^\
。这就是输出中
包含两者的原因。^\
解决方案是(从 awk 程序)收回对如何创建数组索引的控制权。最简单的解决方案是将两个字段 ($1
和$2
) 连接在一起,但这将使这两个数组键相等(没有特定的语言):
$1=abc $2=def $1$2 is abcdef
$1=a $2=bcdef $1$2 is abcdef
解决方案是使用未出现在 $1 或 $2 的值中的字符。空格似乎是一个候选者,但 FS(字段分隔符)是一种更通用的解决方案,它也可以在打印时分隔字段。因此,该脚本适用于任何 FS:
#!/bin/bash
# Merge two cross section files from Resummino
file1=filein1
file2=filein2
fileout=fileout
awk 'BEGIN{OFS=FS} {
point = $1 FS $2
xs_nlo[ point ] += $4
xs_lo [ point ] += $3
}
END {
for (xs in xs_nlo){
print(xs, xs_lo[xs], xs_nlo[xs])
}
}
' "${file1}" "${file2}"
答案3
更换xs_nlo[$1," ",$2]
固定xs_nlo[$1" "$2]
它。