1

# 修复症状

您如何有效地总结以下列?

第 1 列

1
3
3
...   

第 2 栏

2323
343
232
...

这应该给我

预期结果

2324
346
235
...

我有两个文件中的列。


# 初始情况

我有时会使用太多的大括号,以至于我在文件中使用了 this { 比 this } 多一个。我试图找到我在哪里使用了一个不必要的大括号。我已使用以下步骤获取数据

查找命令

 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

使用蟒蛇:

totals = [ int(i)+int(j) for i, j in zip ( open(fname1), open(fname2) ) ]
于 2009-08-28T14:46:28.447 回答
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 程序,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”的记录,并且任何打印语句都将附加“\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 中关联的值$_(将是 '{' 或 '}',见上文)加一。

于 2009-08-28T14:53:38.890 回答
1

在 Python(或 Perl、Awk 和 c)中,你可以合理地在一个独立的“pass”中完成它——我不确定你所说的“太多花括号”是什么意思,但你肯定可以计算每个花括号的使用文件。例如(除非您必须担心多 GB 文件),使用花括号最多的 10 个文件:

import heapq
import os
import re

curliest = dict()

for path, dirs, files in os.walk('.'):
  for afile in files:
    fn = os.path.join(path, afile)
    with open(fn) as f:
      data = f.read()
      braces = data.count('{') + data.count('}')
    curliest[fn] = bracs

top10 = heapq.nlargest(10, curlies, curliest.get)
top10.sort(key=curliest.get)
for fn in top10:
  print '%6d %s' % (curliest[fn], fn)
于 2009-08-28T15:06:39.553 回答
0

回复 Lutz'n 的回答

我的问题终于被这个commnad解决了

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

只需 1 个 awk 命令即可解决您的问题...

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