Я нашел два ответа на предложенная проблема:
Первый предложен @steeldriver:
tr -s ' ' '\n' < file | pr -3t
И второй, который я нашел в другом обсуждении транспонированных матричных элементов:
awk '
{
for (i=1; i<=NF; i++) {
a[NR,i] = $i
}
}
NF>p { p = NF }
END {
for(j=1; j<=p; j++) {
str=a[1,j]
for(i=2; i<=NR; i++){
str=str" "a[i,j];
}
print str
}
}' file
Это однопроходное -решение:
/Nodes/ { read = 1 }
/EndNodes/ { read = 0 }
!read { next }
NF == 4 { n = $1; x = $2; y = $3; z = $4 }
z > max { delete set; i = 1; max = z }
x >= 0 && y == 0 && z == max { set[i++] = n }
END { for (i in set) { print set[i] } }
Переменная read
определяет, должны ли мы действовать с текущей записью или нет. Если это 1, то мы делаем.
Третий блок отбрасывает текущий ввод, если он нас не интересует, и продолжает сверху со следующей записью.
В четвертом блоке задаются четыре удобные переменные: n
, x
, y
и z
. Их приятнее читать, чем $1
и т. д.
5-й блок удаляет массив set
. Массив set
— это набор всех номеров узлов, которые мы нашли до сих пор и которые удовлетворяют критериям. Поскольку этот блок выполняется, если мы нашли новый максимум для z
, все ранее найденные узлы становятся недействительными. Также сохраняем новый максимум(max
). Переменная i
— это просто индекс в массиве (счетчик, в основном ). Если максимум еще не найден, то неинициализированный max
будет считаться нулевым в тесте.
Шестой блок выполняется, когда мы нашли узел, удовлетворяющий критериям. Номер узла сохраняется в массиве set
, а i
увеличивается.
В конце мы перебираем массив set
и выводим его содержимое.
Результат при работе под GNU awk
:
20
31
32
BSD awk
и mawk
, работающие на OpenBSD, создают список в обратном порядке.
awkрешение:
получить _max _nodes.awkскрипт:
#!/bin/awk -f
BEGIN{ max=0 }
NR==FNR{ # processing the 1st input file
if ($4~/^[0-9]/) { # if the 4th field is a number
if($4+0 > max) max=$4+0 # capturing maximal number
}
next
}
{ # processing the 2nd input file (same file)
if ($4~/^[0-9]/ && $2+0>=0 && $3+0==0 && $4+0==max) {
print $1
}
}
Использование:
awk -f get_max_nodes.awk input.txt input.txt
Выход:
20
31
32
У меня недостаточно репутации, чтобы комментировать, поэтому я вынужден ответить ответом. Мой первый комментарий был бы о том, что awk — не лучший инструмент для математики с действительными числами. Это лучше для строк и целых чисел.
Другие моменты в awk :Параграф BEGIN происходит до того, как какие-либо строки будут прочитаны из вашего ввода. Параграф END происходит после прочтения всех строк.
Примечание. :awk не сохраняет и не заботится ни о чем, кроме текущей строки/записи ввода,если вы не предпримете шаги для хранения записей/полей в своем коде. Это должно произойти между BEGIN и END.
Ваш код между этими абзацами только устанавливает/сбрасывает переменные, но ничего не делает с их значениями. По сути, вы могли бы «закрепить» -1 входной файл и направить вывод в cut, чтобы добиться аналогичных результатов.
Похоже, вы намеревались проверить число в столбце 4, чтобы найти max или max1, и вывести столбец 1 только в том случае, если столбец 4 содержит этот максимум, после чего следует успешная проверка столбцов 2 и 3. Эту логику необходимо переместить перед END, если только вы не заботитесь только о последней строке файла.
Помните, что в awk каждая строка ввода (по умолчанию )сравнивается с каждым условием. Если условие истинно, выполняется действие или список действий. Вполне возможно, что несколько условий запускают действия в одной и той же строке.
Мое первое впечатление, что вам нужно -переоценить свой процесс. Определите порядок важности и примите соответствующие меры. Например, для меня первый порядок важности воздействует только на данные между двумя флагами в моем входном файле. Затем определите, могут ли действительные числа в каждом из 4 полей быть преобразованы в (или обработаны как )целые числа (или строки )без потери их значения. Сами фактические данные не нужно менять, только их представление в вашем коде. Их можно преобразовать обратно, но вероятность потери точности исходного числа высока. Наконец, выберите, нужно ли вам сохранять все/любые из этих несортированных, случайных данных для последующей обработки или выдавать немедленный вывод построчно.
Следующий мета-пример можно было бы сделать намного эффективнее... Начните с флага, чтобы вы знали, пора ли начать синтаксический анализ. Вы уже видели строку $0 ~= /Nodes/? старт=0.Вы также можете подготовиться к тому, чтобы знать, когда прекратить синтаксический анализ данных, проверив строку $0 ~= /EndNodes/, stop=0. И вам может понадобиться счетчик, если вы храните данные, count=0.
BEGIN {
start=0
stop=0
count=0
max=0
}
/EndNodes/ {
stop=1
}
/Nodes/ {
start=1
}
NF==4 {
if (start==1 && stop==0) {
count++
column1[count]=$1
column2[count]=substr($2,1,index($2,".")-1)
column3[count]=substr($3,1,index($3,".")-1)
column4[count]=substr($4,1,index($4,".")-1)
}
}
# Now print column1 if column2 is non-negative and column3=0 and column4=max
# In the first loop through the array/list, find max
END {
for (loop=1;loop<=count;loop++) {
if (column4[loop]>max) {
max=column4[loop]
}
}
for (loop=1;loop<=count;loop++) {
if (column4[loop]==max && column3[loop]==0 && column2[loop]>=0) {
print column1[loop]
}
}
}
Как написано, вывод будет
20
31
32