在awk、sed或python中基于值和键字符串合并行

在awk、sed或python中基于值和键字符串合并行,python,bash,sed,awk,Python,Bash,Sed,Awk,我有以下输入表: 1 2 A "aaa" 3 4 A "aaa" 5 6 A "aaa" 1 2 B "bbb" 3 4 B "bbb" 1 2 A "ccc" 我想得到: output1-从输入分别打印第1列和第2列中的最低值和最高值,并在第4列中使用相同的名称 1 6 A "aaa" 1 4 B "bbb" 1 2 A "ccc" output2-来自第1列和第2列“行之间”的输入

我有以下输入表:

  1 2   A   "aaa"
  3 4   A   "aaa"
  5 6   A   "aaa"
  1 2   B   "bbb"
  3 4   B   "bbb"
  1 2   A   "ccc"
我想得到:

output1-从输入分别打印第1列和第2列中的最低值和最高值,并在第4列中使用相同的名称

  1 6   A   "aaa"
  1 4   B   "bbb"
  1 2   A   "ccc"
output2-来自第1列和第2列“行之间”的输入打印值;将第2列(第1行)和第1列(第2行)中的值放入第4列中具有相同名称的新行1(当第4列中的名称更改时跳过,如输入的第3、5、6行)

我非常感谢你的建议


提前谢谢

这里有一种使用
awk

awk '!b[$3" "$4]||b[$3" "$4]>$1 {b[$3" "$4]=$1} !t[$3" "$4]||b[$3" "$4]<$2 {t[$3" "$4]=$2} END {for (i in b) print b[i],t[i],i}' file
1 2 A "ccc"
1 6 A "aaa"
1 4 B "bbb"

awk'!b[$3”“$4]| | b[$3”“$4]>$1{b[$3”“$4]=$1}!t[$3”“$4]| b[$3”“$4]$1{b[$4]=$1}!在python中,您可以尝试以下解决方案。我对它进行了编辑,使它不仅能接受索引中的连续数字

# -*- encoding: utf-8 -*-

def get_min_max_index(data):
    result = dict()
    names = set([record[3] for record in data])
    for name in names:
    name_records = filter(lambda record: record[3] == name, data)
    name_indices = map(lambda record: (record[0], record[1]), name_records)
    record_id = name_records[0][2]
    result[name] = (min(name_indices)[0], max(name_indices)[1], record_id, name_indices)
    return result

def get_between_rows(data):
    records_min_max = get_min_max_index(data)
    result = list()
    for i in range(len(data) - 1):
    name = data[i][3]
    max_ind = records_min_max[name][1]
    if data[i][1] < max_ind:
        result.append([data[i][1], data[i+1][0], data[i][2], data[i][3]])
    return result

if __name__ == "__main__":
    import sys
    data = list()
    for line in sys.stdin.readlines():
    line = line.strip().split()
    data.append([int(line[0]), int(line[1]), line[2], line[3].strip('"')])
    for name, line in get_min_max_index(data).items():
    print('{0} {1} {2} {3}'.format(line[0], line[1], line[2], name))
    print('\n')
    for line in get_between_rows(data):
    print('{0} {1} {2} {3}'.format(line[0], line[1], line[2], line[3]))


# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

很多人都可以回答这个问题,但由于OP的努力不足,这里没有答案。很抱歉,我只是一个初学者,我尝试用awk中的一些单行程序来解决is,但没有真正的进展:(谢谢你的回答,它是这样做的,但考虑两栏3美元和4美元,我想只考虑撇号在4美元之间,即AAA或BBB与列<代码> 3”/代码>,如果它的变化,它不与<代码>第4版/代码>相同,那么打印什么,第一次点击,最后?我更新了我的帖子,没有列“3AWAK”!b[$4]| | b[$4]>$1{b[$4]=$1}!t[$4]| b[$4]$1{z[$4]=$3}结束{对于(b中的i)打印b[i],t[i],z[i],i}文件FielIT将工作,但只有字段3和4连接到相同的信息。谢谢,现在它完成了任务,你知道如何指定名称,而不是列4;如果列4中有多个值,我想在撇号中考虑一个,谢谢,抱歉,看起来我过于简化了示例,在实际数据中,数字是通常不是连续的,但对于第4列中的给定名称,它们总是增加(在省略号之间指定)请查看我的更新答案。我想你可以自己做一点努力:)再问一个问题;如果表中有更多的列,我只想按原样打印(假设在数字之前还有两列),这样做的最佳方法是什么;我不太明白第9行中记录id的解决方案:)结果[name]=(记录[0],记录[1],最小值(名称索引)[0],最大值(名称索引)[1],记录id,名称索引)?列表名称索引包含给定行的前两个值,由它指定。我调用
name
行末尾的字符串,如
aaa
bbb
等。例如,第一行
name\u索引将是
(1,2)
。如果您希望在开始处有更多的列(比如说两个新列),这将把与
record
相关的所有内容向右移动。例如,您将有
(记录[2],记录[3])
在以
name\u index=
开头的行上,而不是
(记录[0],记录[1])
,因为您没有定义
行:)
awk '!b[$4]||b[$4]>$1 {b[$4]=$1} !t[$4]||b[$4]<$2 {t[$4]=$2} {z[$4]=$3} END {for (i in b) print b[i],t[i],z[i],i}' file
1 6 A "aaa"
1 2 A "ccc"
1 4 B "bbb"
# -*- encoding: utf-8 -*-

def get_min_max_index(data):
    result = dict()
    names = set([record[3] for record in data])
    for name in names:
    name_records = filter(lambda record: record[3] == name, data)
    name_indices = map(lambda record: (record[0], record[1]), name_records)
    record_id = name_records[0][2]
    result[name] = (min(name_indices)[0], max(name_indices)[1], record_id, name_indices)
    return result

def get_between_rows(data):
    records_min_max = get_min_max_index(data)
    result = list()
    for i in range(len(data) - 1):
    name = data[i][3]
    max_ind = records_min_max[name][1]
    if data[i][1] < max_ind:
        result.append([data[i][1], data[i+1][0], data[i][2], data[i][3]])
    return result

if __name__ == "__main__":
    import sys
    data = list()
    for line in sys.stdin.readlines():
    line = line.strip().split()
    data.append([int(line[0]), int(line[1]), line[2], line[3].strip('"')])
    for name, line in get_min_max_index(data).items():
    print('{0} {1} {2} {3}'.format(line[0], line[1], line[2], name))
    print('\n')
    for line in get_between_rows(data):
    print('{0} {1} {2} {3}'.format(line[0], line[1], line[2], line[3]))


# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
1 6 A aaa
1 4 B bbb
1 2 A ccc


2 3 A aaa
4 5 A aaa
2 3 B bbb