Пока ничто не заменило ShiftIT.
Я наткнулся на Shellshape , что немного приблизило меня к тому, чего я хотел достичь.
BlueTile -> Не удалось запустить его в Debian. Сетка -Плагин -> Невозможно скомпилировать.
Как заметил другой автор, возможно, лучше рассмотреть лучший оконный менеджер, -более ориентированный на клавиатуру.
awk 'BEGIN{ FS=OFS="\t" }
{ data[$2]= (data[$2]==""?"":(k[$2]==$1? data[$2] ORS: "@") ) $0; k[$2]=$1 }
END{ for(x in data) if(data[x] !~/^@/) print data[x] }' infile
примечание :Я использовал символ @
для обозначения тех записей, которые не следует печатать при печати, поэтому этот символ не должен быть представлен во входном файле, иначе вам нужно будет изменить его на другой символ. символ (или вместо )выберите набор символов в виде строки.
data[$2]= (data[$2]==""?"":(XXX) ) $0
, обновляет значение массива data
результатом части (XXX)
, если он не пуст, и добавляет к нему текущую строку. столбец $2
используется как ключи массива.
часть (XXX)
, которая является (k[$2]==$1? data[$2] ORS: "@")
, устанавливает в -символ знака, если значение того же ключа (мы использовали массив t
в качестве помощника для хранения пар последних значений ключей )отличается, иначе добавьте его содержимое + новую строку (ORS )для этого ключа.
в конце все те строки, которые имеют один и тот же второй столбец, но разные > 1 кратный первый столбец, будут удалены, так как мы пометили те, которые имеют определенный символ @
в коде.
чтобы лучше понять код, вы можете использовать оператор print...
всякий раз, когда хотите увидеть, что происходит,
awk 'BEGIN{ FS=OFS="\t" }
{ data[$2]= (data[$2]==""?"":(k[$2]==$1? data[$2] ORS: "***") ) $0; k[$2]=$1 }
END{ for(x in data) print "<" data[x] ">" }' infile
Я только что пометил удаленные записи знаком at -в исходной команде, показав здесь те, которые начинаются со значка ***
.
Использование любого awk, поддерживающегоlength(array)
:
$ cat tst.awk
BEGIN { FS=OFS="\t" }
$2 != prev {
if ( NR > 1 ) {
prt()
}
prev = $2
}
{ cnt[$1]++ }
END { prt() }
function prt( val,i) {
if ( length(cnt) == 1 ) {
for (val in cnt) {
for (i=1; i<=cnt[val]; i++) {
print val, prev
}
}
}
delete cnt
}
$ sort -t$'\t' -k2,2 -k1,1 file | awk -f tst.awk
GL89 AADAC
GL60 AC100
GL60 AC100
GL20 AC200
GL30 AC300
GL30 AC400
GL89 AFDAC
GL89 AFGAC
Подходящей структурой данных для этой задачи является set
иdictionary
И в Python встроены -.
python3 -c 'import sys
ifile = sys.argv[1]
fs,ors = "\t","\n"
d = {}; L = {}
with open(ifile) as fh:
for l in fh:
c1,c2 = l.rstrip().split(fs)
if c2 in d:
d[c2].add(c1)
L[c2].append(l.rstrip())
else:
d[c2] = { c1 }
L[c2] = [ l.rstrip() ]
print(*[l
for k,v in d.items()
if len(v) == 1
for l in L[k]
], sep=ors)
' file
Выход:
GL89 AADAC
GL89 AFGAC
GL89 AFDAC
GL60 AC100
GL60 AC100
GL20 AC200
GL30 AC300
GL30 AC400
Просто так 1 , используя Миллер
Основные шаги
используйте nest --implode
, чтобы собрать все значения $1
, соответствующие каждому $2
, в список с разделителями
отфильтровать список для подсчета уникальных значений$1
используйте nest --explode
, чтобы развернуть отфильтрованные $1
значения обратно в виде отдельных записей
Для шага (2 )мы можем де -дублировать элементы списка с разделителями, например GL50;GL50;GL79;GL99;GL99
, превратив их в ключи в хэш-карте. К сожалению, встроенная строка DSL с -по -функции хэш-карты splitkv
и splitkvx
работают только с парами ключей -значение -, кажется, нет способа (путем передачи разделитель пустых пар, например ), чтобы они превратили строку ключей с разделителями в хэш-карту (с произвольными или пустыми значениями ). Итак, мы должны свернуть свою собственную, разбив строку на индексированную карту, а затем превратив значения в ключи новой карты.
Обратите внимание, что шаги (2 )и (3 )необходимы только потому, что мы не хотим отфильтровывать несколько значений одного и того же $1
value -иначе мы могли бы просто проверить длину индексированной карты сжатой строки (и не было бы необходимости разбивать результат ).
Итак,
$ mlr --nidx --fs tab nest --ivar ';' -f 1 then filter '
func splitkx(s,t):map {
var m = {};
for(k,v in splitnvx(s,t)){m[v] = 1};
return m
}
length(splitkx($1,";")) == 1' then nest --evar ';' -f 1 file
GL89 AADAC
GL89 AFGAC
GL89 AFDAC
GL60 AC100
GL60 AC100
GL20 AC200
GL30 AC300
GL30 AC400
Примечания: