在一个字段中重复的元素与在另一个字段中重复的另一个元素相关联的印刷线

时间:2018-10-01 22:30:21

标签: bash shell awk

我有一个制表符分隔文件:

scaffold_991    201     SYT3
scaffold_991    9396    SYT3
scaffold_991    11241   SYT3
scaffold_991    204     A
scaffold_991    939     A
scaffold_991    1141    A
scaffold_3006   610     TXNL4A
scaffold_3006   614     TXNL4A
scaffold_82     3098096 TXNL4A
scaffold_82     3100933 TXNL4A
scaffold_997    667     SPNS1
scaffold_997    1241    SPNS1
scaffold_997    2722    SPNS1
scaffold_997    3618    SPNS1
scaffold_997    9410    SPNS1
scaffold_997    18724   SPNS1

...

我需要打印字段3中的名称(SYT3,TXNL4A,SPNS1,...)与字段1中的同一元素没有关联的所有行。

因此输出为:

scaffold_3006   610     TXNL4A
scaffold_3006   614     TXNL4A
scaffold_82     3098096 TXNL4A
scaffold_82     3100933 TXNL4A

或者,如果更简单,这也应该起作用:

scaffold_991    201     SYT3
scaffold_991    9396    SYT3
scaffold_991    11241   SYT3
scaffold_991    204     A
scaffold_991    939     A
scaffold_991    1141    A
scaffold_997    667     SPNS1
scaffold_997    1241    SPNS1
scaffold_997    2722    SPNS1
scaffold_997    3618    SPNS1
scaffold_997    9410    SPNS1
scaffold_997    18724   SPNS1

换句话说,第3列中相同的重复元素必须与第1列中相同元素的重复关联。

我找不到任何类似的问题,也不足够自己尝试。

我还在第3列(SYT3,TXNL4A,SPNS1)中列出了唯一元素。

我注意到,对第一列进行排序只会在第3列中相同元素的重复进行拆分,前提是该元素存在多个支架,从而导致:

scaffold_82     3098096 TXNL4A
scaffold_82     3100933 TXNL4A
scaffold_991    201     SYT3
scaffold_991    9396    SYT3
scaffold_991    11241   SYT3
scaffold_991    204     A
scaffold_991    939     A
scaffold_991    1141    A
scaffold_997    667     SPNS1
scaffold_997    1241    SPNS1
scaffold_997    2722    SPNS1
scaffold_997    3618    SPNS1
scaffold_997    9410    SPNS1
scaffold_997    18724   SPNS1
scaffold_3006   610     TXNL4A
scaffold_3006   614     TXNL4A

...

我想找出实例,其中第3列中的给定元素在文件中的不同位置(由另一个元素分隔开)至少第二次重复了一次,这是对此的另一种思考方式:

这样我就可以得到输出:

scaffold_3006   610     TXNL4A
scaffold_3006   614     TXNL4A

,然后可以删除所有包含TXNL4A的行。

3 个答案:

答案 0 :(得分:1)

我认为您的问题可以简化为在field3中查找那些值,而field1中的值并不相同。因此,对于field3中的每个值,您需要检查field1中该field3的值是否全部相同,如果不相同,则应打印出与该field3相同的所有行。

将输入保存到0 foo 2 baz 中,我可以:

app/services/payment_gateway/stripe_client.rb

但是我觉得一个循环中多次读取文件并不适合大文件,所以我想出了这个:

input.txt

如果值的顺序很宝贵,则需要首先获取column3的所有值以进行打印,然后使用grep进行打印:

cut -f 3 input.txt | sort -u |                              # get all unique fields from column 3
while read -r field3; do                                    # for each field in column 3
    tmp=$(grep $'\t'"$field3"'$' input.txt)                 # I get only values for this column                                         
    if [ "$(<<<"$tmp" cut -f1 | uniq | wc -l)" -ne 1 ]; then  # if the values in the column1 are not unique
        <<<"$tmp" cat                                          # then print all the values of column 3
    fi
done

可通过tutorialspoints获得实时版本。

答案 1 :(得分:1)

对于真正的多维数组,使用GNU awk:

$ awk '
    { map[$3][$1] = map[$3][$1] $0 ORS }
    END {
        for (f3 in map) {
            if (length(map[f3]) > 1) {
                for (f1 in map[f3]) {
                    printf "%s", map[f3][f1]
                }
            }
        }
    }
' file
scaffold_82     3098096 TXNL4A
scaffold_82     3100933 TXNL4A
scaffold_3006   610     TXNL4A
scaffold_3006   614     TXNL4A

答案 2 :(得分:1)

这可能有效(尽管可能有更好的解决方案):

awk '{a[$3][$1][$0]=1}END{for (i in a) if (length(a[i])>1) for (j in a[i]) for (k in a[i][j]) print k}' file
  • a[$3][$1][$0]=1}$3$1分组的行创建索引
  • for (...) for (...) for (...)打印每个组中的所有行,其中$1的行$3

输出:

scaffold_82     3100933 TXNL4A
scaffold_82     3098096 TXNL4A
scaffold_3006   614     TXNL4A
scaffold_3006   610     TXNL4A