обычный awk -простая сортировка индексов массива для вывода их в выбранном порядке

Это во многом зависит от машины, о которой мы говорим... в настоящее время на ПК устройства назначают номера IRQ на лету при настройке.

Чтобы углубиться в тему, загляните в «Драйверы устройств Linux»(да, он довольно устарел, но многое из того, что в нем сказано, по-прежнему применимо ).

7
18.09.2020, 14:44
2 ответа
$ cat tst.awk
{ cnt[$0]++ }
END {
    n = sort(cnt,idxs)
    for (i=1; i<=n; i++) {
        idx = idxs[i]
        printf "%s:%d%s", idx, cnt[idx], (i<n ? OFS : ORS)
    }

}

function sort(arr, idxs, args,      i, str, cmd) {
    for (i in arr) {
        gsub(/\047/, "\047\\\047\047", i)
        str = str i ORS
    }

    cmd = "printf \047%s\047 \047" str "\047 |sort " args

    i = 0
    while ( (cmd | getline idx) > 0 ) {
        idxs[++i] = idx
    }

    close(cmd)

    return i
}

# create the 2 basic files to be parsed by the awk:
printf 'a b a a a c c d e s s s s e f s a e r r f\ng f r e d e z z c s d r\n' >fileA
printf 's f g r e d f g e z s d v f e z a d d g r f e a\ns d f e r\n'>fileB

for f in fileA fileB ; do
    printf 'for file: %s: ' "$f"
    tr ' ' '\n' < "$f" |
    awk -f tst.awk
done
for file: fileA: a:5 b:1 c:3 d:3 e:5 f:3 g:1 r:4 s:6 z:2
for file: fileB: a:2 d:5 e:5 f:5 g:3 r:3 s:3 v:1 z:2

Приведенный выше код просто строит новую строку -разделенную строку из индексов массива (, заключая ее в соответствующие кавычки для sh), создает сценарий оболочки, который направляет эту строку в sort, а затем выполняет цикл на выходе. Если вы хотите изменить поведение sort, просто добавьте строку аргументов Unix sortк вызову функции sort, например. sort(seen,"-fu"). Очевидно, его можно изменить, чтобы он печатал или делал все, что вы хотите, внутри функции sort()вместо заполнения массива индексов, чтобы вы могли зацикливаться, когда он возвращается, если это то, что вы предпочитаете, но тогда функция такая же связная.

Обратите внимание, однако, что это будет ограничено максимальной длиной командной строки в вашей системе.

\047в коде представляют ', которые оболочка не позволяет включать в'-строки или сценарии с разделителями, поэтому, хотя мы могли бы использовать 'непосредственно в сценарии awk, считываемом из файл, как я делаю выше, если бы вы использовали этот скрипт в командной строке как awk 'script' file, вам нужно было бы использовать что-то вместо ', и \047работает как при интерпретации скрипта из командной строки и из файла, так что это самый портативный вариант замены '-.

's(\047s )присутствуют в кавычках strтаким образом, что оболочка не расширяет переменные, не имеет несоответствующих кавычек и т. д., когда строка передается по конвейеру для сортировки., т.е. они делают это:

$ echo 'foo'\''bar $(ls) $HOME' | awk '{
    str=$0; gsub(/\047/, "\047\\\047\047", str); print "str="str
    cmd="printf \047%s\047 \047" str "\047"; print "cmd="cmd
}'
str=foo'\''bar $(ls) $HOME
cmd=printf '%s' 'foo'\''bar $(ls) $HOME'

поэтому мы не получаем что-то подобное, что является уязвимым/глючным, вместо этого:

$ echo 'foo'\''bar $(ls) $HOME' | awk '{
    str=$0; print "str="str
    cmd="printf \"%s\" \"" str "\""; print "cmd="cmd
}'
str=foo'bar $(ls) $HOME
cmd=printf "%s" "foo'bar $(ls) $HOME"
4
18.03.2021, 23:04

С помощью GNU awkвы можете выполнять двустороннее -взаимодействие с sortс его функцией «совместной обработки» (info gawk coproc), где вы отправляете данные для сортировки с помощью print |& "sort"и получаете результат. с "sort" |& getline, но опять же, это специфично для зевак.

Чтобы перебрать массив в порядке его появления , вы можете записать эту последовательность встреч во время заполнения массива:

awk '
  !seen[$1]++ {sequence[n++] = $1}
  END {
    for (i = 0; i < n; i++)
      print sequence[i], seen[sequence[i]]
  }'

Вы также можете реализовать алгоритм сортировки в awk. Вы даже можете позаимствовать gawkу quicksort.awk, вы даже найдете его в его руководстве(здесь, чтобы продемонстрировать косвенные вызовы функций, еще одну особенность GNU -, вы бы заменили ее на буквальный вызов вашей процедуры сравнения ). Что-то вроде:

awk '
  function less_than(left, right) {
    return "" left <= "" right
  }
  function quicksort(data, left, right,   i, last)
  {
    if (left >= right)
      return

    quicksort_swap(data, left, int((left + right) / 2))
    last = left
    for (i = left + 1; i <= right; i++)
      if (less_than(data[i], data[left]))
        quicksort_swap(data, ++last, i)
    quicksort_swap(data, left, last)
    quicksort(data, left, last - 1)
    quicksort(data, last + 1, right)
  }
  function quicksort_swap(data, i, j,   temp)
  {
    temp = data[i]
    data[i] = data[j]
    data[j] = temp
  }

  {seen[$1]++}
  END {
    for (i in seen) keys[n++]=i
    quicksort(keys, 0, n-1)
    for (i = 0; i < n; i++)
      print keys[i], seen[keys[i]]
  }'

Лично я бы использовал здесь perlвместо awk.

5
18.03.2021, 23:04

Теги

Похожие вопросы