1

# 症状を改善するには

次の列を効果的に要約するにはどうすればよいですか?

列 1

1
3
3
...   

列 2

2323
343
232
...

これは私に与えるはずです

期待される結果

2324
346
235
...

2 つのファイルに列があります。


# 初期状態

ファイル内で this { よりも this } を 1 つ多く使用するように、中括弧が多すぎる場合があります。不要な中括弧をどこで使用したかを見つけようとしています。データを取得する際に次の手順を使用しました

コマンドを探す

 find . * -exec grep '{' {} + > /tmp/1
 find . * -exec grep '}' {} + > /tmp/2

AWK コマンド

 awk -F: '{ print $2 }' /tmp/1 > /tmp/11
 awk -F: '{ print $2 }' /tmp/2 > /tmp/22

列はファイル /tmp/11 および /tmp/22 にあります。

私の手順では、多くの同様のコマンドを繰り返します。これは、これが正しい方法ではないことを示唆しています。

ステップ数を減らすことができるPython、Perl、またはUnixツールなどの方法を提案してください。

4

6 に答える 6

11

c1 と c2 が自分のファイルである場合、次のように実行できます。

$ paste c1 c2 | awk '{print $1 + $2}'

または (AWK なし):

$ paste c1 c2 | while read i j; do echo $(($i+$j)); done
于 2009-08-28T14:53:43.723 に答える
3

カウントと比較を同時に行うコマンドを使用するだけで、中間ステップを回避できます。

find . -type f -exec perl -nle 'END { print $ARGV if $h{"{"} != $h{"}"} } $h{$_}++ for /([}{])/g' {}\;

これにより、Perl プログラムがファイルごとに 1 回呼び出されます。Perl プログラムは、各タイプの中括弧の数をカウントし、カウントが一致しない場合はファイルの名前を出力します。

/([}{]])/セクションに注意する必要がfindあり{}ます/([{}]])/

警告: このコードをソース コードに対して実行しようとすると、誤検出と誤検出が発生します。次のケースを考慮してください。

バランスがとれていますが、文字列のカーリー:

if ($s eq '{') {
    print "I saw a {\n"
}

アンバランスですが、文字列のカーリー:

while (1) {
   print "}";

B::Deparseを使用して Perl コマンドを展開できます。

perl -MO=Deparse -nle 'END { print $ARGV if $h{"{"} != $h{"}"} } $h{$_}++ for /([}{])/g'

結果は次のとおりです。

BEGIN { $/ = "\n"; $\ = "\n"; }
LINE: while (defined($_ = <ARGV>)) {
    chomp $_;
    sub END {
        print $ARGV if $h{'{'} != $h{'}'};
    }
    ;
    ++$h{$_} foreach (/([}{])/g);
}

プログラムの各部分を見てみましょう。

BEGIN { $/ = "\n"; $\ = "\n"; }

これは-lオプションが原因です。入力と出力の両方のレコード セパレータを "\n" に設定します。これは、読み込まれたものはすべて "\n" ベースのレコードに分割され、すべての print ステートメントには "\n" が追加されることを意味します。

LINE: while (defined($_ = <ARGV>)) {
}

これは-nオプションによって作成されます。コマンドライン (ファイルが渡されない場合は STDIN) を介して渡されたすべてのファイルをループし、それらのファイルの各行を読み取ります。これは$ARGV、 によって最後に読み取られたファイルにも設定され<ARGV>ます。

chomp $_;

$/これにより、読み取られたばかりの行から変数にあるものはすべて削除されます( $_)。ここでは何も役に立ちません。-lオプションが原因でした。

sub END {
    print $ARGV if $h{'{'} != $h{'}'};
}

これは END ブロックです。このコードはプログラムの最後に実行されます。キーに関連付けられた と に格納されている値が等しい場合、(最後に読み取ら$ARGVれたファイルの名前。上記を参照) が表示されます。%h'{''}'

++$h{$_} foreach (/([}{])/g);

これはさらに分解する必要があります。

/
    (    #begin capture
    [}{] #match any of the '}' or '{' characters
    )    #end capture
/gx

一致する文字列に含まれる「{」および「}」文字のリストを返す正規表現です。文字列が指定されていないため、$_変数 (ファイルから最後に読み取られた行を保持します。上記を参照) と照合されます。そのリストは、リストforeach内の各項目 (したがって名前) に対して前にあるステートメントを実行するステートメントに入力されます。また、 ( Perl では一般的な変数である$_ことがわかるように) リストの項目になるように設定します。$_

++h{$_}

この行は、関連付けられている $h の値$_('{' または '}' のいずれか、上記を参照) を 1 増やします。

于 2009-08-28T14:53:38.890 に答える
0

あなたの問題はたった1つのawkコマンドで解決することができます...

awk '{getline i<"file1";print i+$0}'  file2
于 2009-08-30T14:12:44.973 に答える
0

ルッツンアンサーに返信

私の問題は最終的にこのコマンドによって解決されました

paste -d: /tmp/1 /tmp/2 | awk -F: '{ print $1 "\t" $2 - $4 }'
于 2009-08-28T15:29:00.260 に答える