Вы можете просто сделать это в awk
, идентифицируя первый файл, который вы используете для справки, и игнорируя его для последующей обработки, используя опцию nextfile
(требуется версия GNU), которая пропускает обработку файла для последующей обработки. Исходя из этой логики, вы должны разместить справочный файл, например, file.4.dat
в качестве входных данных в качестве первого аргумента в списке файлов.
awk '
BEGIN{ ignoreFile = ARGV[1] }
NR==FNR {
a[$1]=$2
next
}
FILENAME == ignoreFile { nextfile }
($1 in a) {
a[$1]+=$2
}
END {
for(i in a)
print i,a[i]
}' file.4.dat file.[1-5].dat >| test.out
ОП хотел знать, могут ли они создать список шаблонов имен файлов, которые можно сгенерировать из оболочки и использовать. Это можно сделать, но, учитывая относительно более простой вариант, доступный в nextfile
, это может показаться сложным.
Из вашего понимания у вас есть n
файлы, и один из них будет использоваться в качестве справочного файла. Я бы предпочел использовать функцию extglob оболочки bash
, чтобы включить все файлы, кроме ссылки. Например, Я создаю файлы file1..10
для объяснения этого
touch file{1..10}
exclude=3
Параметры расширенной оболочки устанавливаются с помощью встроенного shopt
shopt -s extglob
list=(!(file"$exclude"))
. Теперь распечатайте массив, используя declare -p list
чтобы увидеть список файлов только с опорным файлом. Теперь используйте массив в вашем awk
, как показано ниже. Расширение массива "${list[@]}"
приводит к исключению всех файлов, сгенерированных вами выше.
awk ... file"$exclude" "${list[@]}"
Насколько я знаю, не существует ни одного, и Set по своей математической природе должен быть неупорядоченным (или по крайней мере, на практике это означало не гарантировать порядок - фактически он обычно реализован в виде хеш-таблицы, поэтому он портит порядок).
Тем не менее, нетрудно либо напрямую расширить массив, либо сделать его подклассом для этого. Я только что попробовал, и это работает:
class UniqueArray < Array
def initialize(*args)
if args.size == 1 and args[0].is_a? Array then
super(args[0].uniq)
else
super(*args)
end
end
def insert(i, v)
super(i, v) unless include?(v)
end
def <<(v)
super(v) unless include?(v)
end
def []=(*args)
# note: could just call super(*args) then uniq!, but this is faster
# there are three different versions of this call:
# 1. start, length, value
# 2. index, value
# 3. range, value
# We just need to get the value
v = case args.size
when 3 then args[2]
when 2 then args[1]
else nil
end
super(*args) if v.nil? or not include?(v)
end
end
Кажется, чтобы охватить все основы. Я использовал удобную Ruby Cookbook от OReilly в качестве справочного материала - у них есть рецепт «Обеспечение того, чтобы отсортированный массив оставался отсортированным», что аналогично.
You could use a Hash to store the values, and have an incrementing value stored in the value of each Hash pair. Then you can access the set in a sorted manner, albeit slowly, by accessing the objects via their values.
I'll try to add some code in here later to explain further.
I am aware accessing via values is much slower than by keys.
Update 1: In Ruby 1.9, Hash elements are iterated in their insertion order.
Не то чтобы я знал об этом, но было бы нетрудно накатить свой собственный. Просто создайте подкласс Array и используйте Set для поддержания ограничения уникальности.
Один вопрос о немом отбрасывании. Как это повлияет на # [] =? Если я пытаюсь перезаписать существующую запись чем-то, что уже было сохранено где-то еще, следует ли в любом случае удалить элемент, который будет удален? Я думаю, что в любом случае в будущем могут возникнуть неприятные сюрпризы.