awk 输出中的控制字符

awk 输出中的控制字符

我有以下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]它。

相关内容