2つの列の値を組み合わせるにはどうすればよいですか?


11

次の形式のファイルがあります。

$ cat /tmp/raw
2015-01   5000   1000
2015-02   6000   2000
2015-03   7000   3000

次に、各行の列2と3から結合された値を取得して、結果が次のようになるようにします。

2015-01   6000
2015-02   8000
2015-03   9000

私はこれを試しましたが、2015-03の値のようなファイルの最後の値しか表示されません。

回答:


11

次を使用して試すことができますawk

awk '{ print $1, $2 + $3; }' /tmp/raw

結果は次のようになります(2015-03の値は10000になるはずです):

2015-01 6000
2015-02 8000
2015-03 10000

1
こんなに早く返事が来たとは信じられない:O、他のフォーラムでは
そんなに

@SyedJahanzaib、この回答で問題が解決した場合は、少し時間を取って、左側のチェックマークをクリックして同意してください。これにより、質問に回答済みのマークが付けられ、Stack Exchangeサイトで感謝の意が表明されます。
terdon

すみません、答えをマークするのを忘れていました。貴重な時間と返信をありがとうございました。他にもさまざまな方法で目標を達成できるようになりました:)
Syed Jahanzaib

@SyedJahanzaib、私はこの回答に対して素晴らしいバッジを獲得しましたが、より正確で包括的であることがterdonの回答だと思います。
taliezin

16

ここにいくつかの方法があります:

  1. 別のawkアプローチ

    awk '{$2+=$3;}NF--' file
    
  2. Perl

    perl -lane 'print "$F[0] ",$F[1]+$F[2]' file
    

    または

    perl -ape 's/$F[1].*/$F[1]+$F[2]/e' file
    
  3. シェル(上記よりはるかに遅い/効率が悪い)

    while read a b c; do echo "$a $((b + c))"; done < file
    

2
$2+=$3もっとぎこちないかもしれません。
123

@ User112638726確かにそうです。ありがとう。
terdon

3
またawk '{$2+=$3}NF--'、空のフィールド3がぶら下がらないように使用することもできます。それは私の好みですが、それだけで回答として投稿するのはあまりにも似ていますが:)
123

1
@ User112638726今、私には思いもよらなかった。とてもすっきり、ありがとう!
terdon

これはあなたのために書きました。するだけでなく、どのように注意sed何とか理解して管理するフィールドをしても定義する- フィールドをその場で、そしてフィールドで/ワットフィールド -しかし、のように明らかにそうである、Unixの正規表現マッチングの全体概念がされ、実際に文字列を分割することに基づいてフィールドパターンに応じて!誰かわかったね?
mikeserv 2015年

5
sed 's/[^ ]* */[&]P/;s//&+pc/3'|dc

...プリント...

2015-01   6000
2015-02   8000
2015-03   10000

したがって、上記の私が宣言正規表現定義フィールド程度で構成され*た可変長される文字の単一のシーケンス^<スペース>ない直後*可変長である文字の単一のシーケンス<スペース>。この宣言はsed、パターンスペースに対して適用されます。\nこれは、入力で発生する各ewline文字で(デフォルトで)区切ら、同じものが出現するたびに(デフォルトで)再帰的に次の文字に置き換えられる文字列です

この宣言のインターフェースは2つあり、各レベルでコマンド構文の予測可能なアプリケーションを確実にするために、少なくとも1つの 国際IEEE公式標準委員会によって完全に規制および指定されていsedます。たとえば、このsedAPI構文は、この場合、/address /コマンド(常に任意のsed s///ubstitutionコマンドの最初のコンポーネントです)で適用されますが、その内容は、より基本的なAPIによって、標準Cライブラリのregcomp()関数。

ので、私は、自信を持ってこれらの文を作ることができるsedはない、むしろ、名前のコンパイルされた実行可能、単にプログラムが、sed私のUnixライクなマシンでは、実装、明確に定義された、歴史的に確立され、基準が制御のsed アプリケーション私のシステムのregular-の式一致ライブラリ。


sedスペックから:

sedユーティリティはで説明BREではサポートしなければならないXBD基本正規表現を ...

...見つけた場所...

BREではとのEREの両方が下POSIX.1-2008のシステムインターフェイスボリュームでの正規表現のマッチング・インターフェースによってサポートされているregcomp()regexec()および関連機能。

を呼び出すアプリケーションはregcomp()パターン文字列を表示し、...

... [t] regcomp()関数は、パターン引数が指す文字列に含まれる正規表現をコンパイルし、結果を構造体preg ...に配置します。

その上で行動するために、そのアプリケーションはregcomp()のコンパニオン関数を参照します...

... [t] he regexec()関数は、stringで指定されたnullで終了する文字列を、前の...の呼び出しで初期化されたコンパイル済みの正規表現pregと比較しますregcomp()

... regexec()のサブストリングのオフセットを有する[]配列の要素を記入しなければならない文字列に対応する\(括弧内の部分式\)パターン ... パターン自体が部分式としてカウント...

... [T]彼はregexec()すべてに記入しなければならない機能nmatchをの要素pmatchnmatchをpmatchは、いくつかの要素も、アプリケーションによって供給されているpmatchは中の部分式に対応していない模様


そして私がするとき...

/[^ ]* */

... sed最初に正規表現をコンパイルし、結果をメモリに格納します。その後、そこに格納されているコンパイル済みオートマトンを、コマンドを実行するために必要な回数だけパターンスペースのコンテンツに適用します。そのたびに、結果は、によって返されるオフセットで区切られた、1つ以上のヌル区切りフィールドの配列になりますregexec()

そして私がするとき...

//

...最後に定義された正規表現を使用する必要があることを示すために、プリコンパイルされた正規表現を再利用して再度sed呼び出すことができますregexec()が、今回は変更された文字列引数に適用するか、コマンドとして新しいnmatchパラメータを適用します

さらに具体的には...

  • s/[^ ]* */[&]P/
    • pattern-spaceで最初に出現するpattern[左角括弧で置き換え、次に&それ自体、次に]右角括弧でP文字を置き換えます。
  • s//&+pc/3
    • 最後に使用された正規表現を現在のパターンスペースに再度適用し、パターンスペースで33番目に出現するパターン&それ自体とその後に追加されたstringで置き換えます+pc

そしてsed、あなたの例のデータを考えると、の入力の各行について、そのstdoutに書き込みます。

[2015-01   ]P5000   1000+pc
[2015-02   ]P6000   2000+pc
[2015-03   ]P7000   3000+pc

これは奇妙に見えるかもしれませんが、dc電卓は角括弧で囲まれた入力内の文字列を引用します。Pコマンドは両方とも、\newline を追加せずにスタックの上部を出力し、その後、入力スタックからポップアウトします。

そして、例として最初の行を使用すると、次のようにdcなります。

  • [2015-01 ]P
    • Pスタックの最上部をrintしてポップする
  • 5000
    • 数値5000をスタックの一番上にプッシュし、現在スタックにあるすべての要素(現在は何もない)を1つ下にプッシュします。
  • 1000
    • 同上ですが、今回はメインスタックの一番上の5000が1つ押し下げられ、スタックの2番目の要素になります。
  • +
    • スタックの上の2つの数値を加算し、両方をスタックからポップして、合計をスタックの一番上にプッシュします。
    • これにより、数値のみで構成されるスタックが生成されます6000
    • スタックの上位2つの要素のいずれかが[文字列である場合、これは構文エラーです]
  • p
    • pスタックの先頭\nからリントし、スタックからポップすることなく、追加されたewlineが続きます。
  • c
    • cスタックを利用する

うまくいくと思いますが、解析できません。全体として、DCの追加を設定しています。最初のパターンは理にかなっています。日付と末尾の空白に一致すると思いますが、文字クラスの角かっこ([&])内に置くと何ができるのかわかりません。これを綴るのは素晴らしいことです。
Joe

1
@ジョー-より良いですか?
mikeserv 2015年

うわー!これはもっと理にかなっています(そして、私がもっと学ぶ必要がある多くのことを私に示します。)特に、現在のパターンを再利用するために//の使用に気づいたことはありませんでした。これは、実際の例に出会うまで読んで忘れてしまうことです。どうもありがとう。非常に小さなコマンドにどれだけのパワーを詰め込むことができるか、そしてそれを説明するのにどれだけかかるかを見て、私は笑いました。
Joe

@ジョー-ええと...多分私は少し船外に行った...
mikeserv
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.