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が、各行の最後の2つの値が異なります。スクリプトawkは、最初の値と2番目の値が同じであると仮定し、各行に3番目の値を追加する必要があります。 4番目の値も同じです。

出力ファイルは入力ファイルと同じ構造を持つ必要があります。コンソールで出力ファイルは同じように見えますが、コンソールで開くとvim簡単に検索できない制御文字が表示されます。

100.000^\ ^\300.000 3.42 4.57283

どういう意味ですか^\ ^\?どのように削除できますか?

答え1

問題の原因は区切り文字です$1," ",$2

ドキュメントから:

awk はインデックスを文字列に連結して多次元配列をサポートします。 awkはインデックスを文字列に変換し(変換を参照)、インデックス間を区切り文字に連結します。これにより、個々のインデックス値を記述する単一の文字列が生成されます。結合された文字列は、通常の1次元配列の単一インデックスとして使用されます。使用される区切り文字は組み込み変数の値です。サブセット


サブセット
下付き文字の区切り記号。デフォルトは「\034これは多次元配列のインデックス部分を分離するために使用されます。したがって、 'foo["A", "B"]' 式は実際には foo["A\034B"] にアクセスします。


標準 awk は、下付き文字の値をカンマで区切って多次元配列をエミュレートします。これらの値は、SUBSEP値で区切られた単一の文字列に連結されます。
したがって、この添え字がこのように生成されるという事実は維持されない。サブセット意図しない結果が生じる可能性があります。

答え2

2番目の部分の場合:

^\ ^\は何を意味し、どのように削除できますか?

他の回答では、カンマ(,)が[$1," ",$2]SUBSEPになる場所を説明しました。 Thtaは文字\034(8進数)または0x1C(16進数)です。

この文字はコントロールエンコーディングにも書き込むことができます^\。そのため、両方とも出力に
含まれます。^\

解決策は、配列インデックスがどのように生成されるかについての制御を(awkプログラムから)取り戻すことです。最も簡単な解決策は、2つのフィールド($1$2)を一緒にリンクすることです。ただし、これにより2つの配列キーが同じになります(言語に関係ありません)。

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

回避策は、$1または$2の値に表示されない文字を使用することです。スペースは候補に見えますが、FS(Field Separator)は印刷時にフィールドも区別するより一般的なソリューションです。したがって、このスクリプトはすべての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]

関連情報