Можно ли использовать строку в качестве индекса в массиве массивов в gawk?

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

find / -type d -name "lib*" -print | wc -l

Это предполагает, что вы, согласно "всему поддереву каталогов", означает «где угодно». Измените /на .для подсчета только в текущем каталоге или ниже.

Команда findнайдет все каталоги (-тип d), имя которых начинается с lib(-name "lib*") и распечатайте их (-print).

Команда wc -lбудет подсчитывать количество строк в выводе команды find.

1
07.03.2017, 14:04
1 ответ

Да, это возможно. Однако проблема в вашем сценарии заключается в том, что вы делаете не то, что (как мне кажется) вы думаете. Во-первых, вы используете i в качестве индекса массива первого уровня:

arr2[i][num] = val

Это означает, что i будет числом от 1 до длины массива и что arr2[i] будет перезаписано, если в любой из ваших строк будет то же самое строковое значение в том же самом поле.

Теперь, причина, по которой вы получаете пустую строку в качестве вывода (я предполагаю, что это то, что вы получаете, на самом деле вы не сказали), заключается в том, что вы используете неправильный порядок в вашем массиве. У вас есть:

arr2[i][num] = val

Так, например:

arr2[1][soo]=9

То, что вы, похоже, ожидаете, это наоборот:

arr2[1][9]=soo

Итак, что вам нужно:

arr2[i][value]=num

Если мы также изменим определение массива, чтобы использовать NR как первичный индекс вместо num, чтобы избежать коллизий, мы получим:

gawk '
{
    split($0,arr)
    for(i=1;i<=length(arr);i++){
        eq=index(arr[i],"=")
        num=substr(arr[i],eq+1)
        val=substr(arr[i],0,eq-1)
        arr2[NR][val] = num
    }
}
END{
  for(i in arr2){
    for (num in arr2[i]){
      printf "arr2[%s][%s]=%s\n", i, num, arr2[i][num]
    }
  }
}
' newfile.txt
arr2[1][3]=bar
arr2[1][9]=foo
arr2[1][30]=bin
arr2[1][71]=bon
arr2[1][84]=baz
arr2[2][3]=gar
arr2[2][9]=goo
arr2[2][30]=gin
arr2[2][71]=gon
arr2[2][84]=gaz
arr2[3][3]=sar
arr2[3][9]=soo
arr2[3][30]=sin
arr2[3][71]=son
arr2[3][84]=saz

Как вы можете видеть, arr2[2][9] теперь goo, как и ожидалось. Однако все это слишком сложно. Вы могли бы упростить его до:

$ awk -F'[ =]' '{
                    for(i=1;i<=NF;i+=2){
                        arr2[NR][$(i)]=$(i+1);
                    }
                } END{print  arr2[2][9]}' newfile.txt 
goo
0
28.01.2020, 01:00

Теги

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