2

我有一个十列的数据列表,如下所示。它有几千行。

$1  $2    $3    $4   $5     $6      $7    $8    $9  $10

|  8455 105@O13  |  8132  101@H13  8131  101@O13 |  68.43
|  7490 93@O16   |  8868  110@H16  8867  110@O16 |  68.30
|  7561 94@O12   |  9185  114@H13  9184  114@O13 |  66.83
|  8776 109@O12  |  7481  93@H12   7480  93@O12  |  65.55
|  8867 110@O16  |  8432  105@H23  8431  105@O23 |  64.48
|  9832 122@O13  |  6357  79@H16   6356  79@O16  |  64.44
|  9194 114@O15  |  5699  71@H12   5698  71@O12  |  64.06
|  8849 110@O25  |  5780  72@H12   5779  72@O12  |  63.99

我想从 $3 列和 $6 列中选择与某些特殊表达式匹配的行。我想用作正则表达式的条件是“两列中“@”符号前的数字相同”。如果匹配此条件,则我想将这些行打印到新文件中。

我在 awk 中尝试过类似的东西

awk '$3~/[1@]/  {print $1,$2,$3,$4,$5,$6,$7,$8,$9,$10}' hhHB_inSameLayer_065_128-maltoLyo12per.tbl

但它没有给我想要的。

如果有人可以在这方面提供帮助,我很感激。

注意:如果我在 perl 或 python 中获得一些帮助,也将不胜感激。

提前谢谢了。

4

7 回答 7

4

在 awk 中尝试以下操作。根据分隔符拆分$3并分成数组,如果每个匹配的第一个元素则打印$6@

awk '{split($3, a, "@"); split($6, b, "@");if (a[1] == b[1]) print}'

或者更惯用的说法

awk '{split($3, a, "@"); split($6, b, "@")}; a[1] == b[1]' 

或者一个快速的 Python 2.6+ 解决方案

from __future__ import print_function
with open('testfile.txt') as f:
    for line in f:
            fields = line.split()
            fields3 = fields[2].split('@')
            fields6 = fields[5].split('@')
            if fields3[0] == fields6[0]:
                    print(line, end='')
于 2013-07-06T04:28:27.920 回答
2

GNU 的代码:

sed -r '/^\|\s+\S+\s+([0-9]+@).*\|.*\1/!d' file

假设有两行的标题:

sed -r '1,2p;/^\|\s+\S+\s+([0-9]+@).*\|.*\1/!d' file
于 2013-07-06T06:12:48.933 回答
1

这是一个使用带有反向引用的单个正则表达式模式的 Perl 单行代码:

perl -ne 'print if m/^\S+\s+\S+\s+(\d+\@)\S+\s+\S+\s+\S+\s+\1/' hhHB_inSameLayer_065_128-maltoLyo12per.tbl > hhHB_inSameLayer_065_128-maltoLyo12per_reduced.tbl

(我很惊讶没有人指出Vijay最初的问题陈述中的明显缺陷:示例中没有符合所述标准的记录。)

于 2013-07-07T01:18:26.707 回答
0
import re

su = '''
$1  $2    $3    $4   $5     $6      $7    $8    $9  $10

|  8455 105@O13  |  8132  101@H13  8131  101@O13 |  68.43
|  7490 93@O16   |  8868  110@H16  8867  110@O16 |  68.30
|  7561 94@O12   |  9185  94@H13  9184  114@O13 |  66.83
|  8776 109@O12  |  7481  93@H12   7480  93@O12  |  65.55
|  8867 110@O16  |  8432  105@H23  8431  105@O23 |  64.48
|  9832 122@O13  |  6357  79@H16   6356  79@O16  |  64.44
|  9194 114@O15  |  5699  71@H12   5698  71@O12  |  64.06
|  8849 110@O25  |  5780  72@H12   5779  72@O12  |  63.99'''

f = re.compile(
    '(^\|[^|]+?[ \t](\S+?)@\S+[ \t]+?'
    '\|[^|]+?[ \t](\\2)@\S+.+)',
    re.MULTILINE)\
    .finditer

print [m.group(1) for m in f(su)]
于 2013-07-07T09:13:35.507 回答
0

叹息,在我想出来之前有三个解决方案......

import re

write_file = open("sorted data.txt", "w")

with open("data.txt", "r") as read_file:
    for line in read_file:
        data_list = re.split("[\s\|@]+", line)
        if data_list[2] == data_list[5]:
            write_file.write(line)

write_file.close()

恐怕我对 perl 或 awk 知之甚少,但是除了 re.split 之外,这很好且可读。

于 2013-07-06T04:54:39.777 回答
0

在 Perl 中:

while( <DATA> ){

  # split the line by whitespace
  my @columns = split;

  # get number from column 3
  my ( $value_col_3 ) = $columns[2] =~ m{ \A (\d+) \@ }msx;

  # get number from column 6
  my ( $value_col_6 ) = $columns[5] =~ m{ \A (\d+) \@ }msx;

  if( $value_col_3 == $value_col_6 ){
    print;
  }
}

__DATA__
|  8455 105@O13  |  8132  101@H13  8131  101@O13 |  68.43
|  7490 93@O16   |  8868  110@H16  8867  110@O16 |  68.30
|  7561 94@O12   |  9185  114@H13  9184  114@O13 |  66.83
|  8776 109@O12  |  7481  93@H12   7480  93@O12  |  65.55
|  8867 110@O16  |  8432  105@H23  8431  105@O23 |  64.48
|  9832 122@O13  |  6357  79@H16   6356  79@O16  |  64.44
|  9194 114@O15  |  5699  71@H12   5698  71@O12  |  64.06
|  8849 110@O25  |  5780  72@H12   5779  72@O12  |  63.99
于 2013-07-06T12:20:09.380 回答
0

这是一个使用内置csv模块的 Python 解决方案。它将所有符合您的条件的行存储在列表中stored_lines

**编辑为跳过标题并且不将多个空格视为多个分隔符。**

import csv

def is_good(line):
    return line[2][:line[2].find('@')] == line[5][:line[5].find('@')]

# we'll put the lines that match the criteria here.
stored_lines = []

with open('stack.txt') as fr:
    csv_reader = csv.reader(fr, delimiter=' ', skipinitialspace=True)

    # Skip the header
    csv_reader.next()
    csv_reader.next()
    for line in csv_reader:
         if is_good(line): stored_lines.append(line)

print(stored_lines)
于 2013-07-06T04:40:54.563 回答