Caractere de controle na saída awk

3

Eu tenho o seguinte script bash / awk , que faz o que eu quero, exceto que ele adiciona um símbolo de controle que eu não sei o que isso significa.

#!/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}"

Possível conteúdo de 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

e similar para filein2 , exceto que os dois últimos valores em cada linha diferem. O script awk deve somar os terceiros valores em cada linha, assumindo que o primeiro e o segundo valores sejam os mesmos. O mesmo para o quarto valor.

O arquivo de saída deve ter a mesma estrutura dos arquivos de entrada. No console, o arquivo de saída parece o mesmo, mas abrindo em vim , vejo um caractere de controle que não é fácil de procurar:

100.000^\ ^0.000 3.42 4.57283

O que isso significa ^\ ^\ e como posso me livrar dele?

    
por pfnuesel 28.06.2017 / 16:57

3 respostas

4

A origem do problema está no separador $1," ",$2 .

Da documentação:

Multidimensional arrays are supported in awk through concatenation of indices into one string. awk converts the indices into strings (see Conversion) and concatenates them together, with a separator between them. This creates a single string that describes the values of the separate indices. The combined string is used as a single index into an ordinary, one-dimensional array. The separator used is the value of the built-in variable SUBSEP

SUBSEP
The subscript separator. It has the default value of "4" and is used to separate the parts of the indices of a multidimensional array. Thus, the expression ‘foo["A", "B"]’ really accesses foo["A4B"]

O awk padrão simula matrizes multidimensionais separando os valores subscritos por vírgulas. Os valores são concatenados em uma única cadeia de caracteres, separados pelo valor de SUBSEP.
O fato de que esse índice foi criado dessa maneira não é retido; Assim, a alteração SUBSEP pode ter consequências inesperadas.

    
por 28.06.2017 / 17:37
1

Para a segunda parte de:

What does this ^\ ^\ mean and how can I get rid of it?

Alguma outra resposta já explicou que a vírgula ( , ) em [$1," ",$2] se torna o SUBSEP. Thta é o caractere 4 (em octal) ou 0x1C (em hexadecimal).

Esse caractere também pode ser escrito na codificação de controle como ^\ .
Essa é a razão para ter os dois ^\ na saída.

A solução é recuperar (do programa awk) o controle de como os índices da matriz são criados. A solução mais simples é concatenar os dois campos ( $1 e $2 ) juntos, no entanto, isso tornará iguais essas duas chaves de matriz (em nenhuma linguagem particular):

$1=abc  $2=def     $1$2 is abcdef
$1=a    $2=bcdef   $1$2 is abcdef

A solução é usar um caractere que não apareça nos valores de $ 1 ou $ 2. O espaço pode parecer um candidato, mas o FS (separador de campo) é uma solução mais geral que também poderia separar os campos quando impressos. Assim, este script funciona para qualquer 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}"
    
por 29.06.2017 / 14:06
0

Substituindo xs_nlo[$1," ",$2] por xs_nlo[$1" "$2] , corrigiu-o.

    
por 28.06.2017 / 17:25