Печать пустых строк при циклическом использовании ассоциативного массива в AWK

#awk

Вопрос:

Я не понимаю, почему печатаются пустые строки вместо их правильных значений из массива day[] в AWK.

 BEGIN{
        day[1]="Sunday"
        day["first"]="Sunday"
        day[2]="Monday"
        day["second"]="Monday"
        day[4]="Wednesday"
        day["fourth"]="Wednesday"
        day[3]="Tuesday"
        day["third"]="Tuesday"
        for (i in day)
        {
            print $i
            print day[$i]
        }
}
 

Явная печать отдельных элементов массива дает ожидаемые значения следующим образом:

  BEGIN{
        day[1]="Sunday"
        day["first"]="Sunday"
        day[2]="Monday"
        day["second"]="Monday"
        day[4]="Wednesday"
        day["fourth"]="Wednesday"
        day[3]="Tuesday"
        day["third"]="Tuesday"
        print day[1]
        print day["first"]
        print day[2]
        print day["second"]
        print day[3]
        print day["third"]
        print day[4]
        print day["fourth"]
}
 

Я использую Linux fedora 5.12.11-300.

Заранее большое спасибо,

Мэри

Ответ №1:

Вы не должны использовать $ при печати i значение или значение массива, так как оно относится к значению поля в awk языке, вместо этого используйте следующее. Также вам не нужно использовать операторы печати 2 раза, вы также можете использовать одинарную печать с новой строкой.

 awk '
BEGIN{
        day[1]="Sunday"
        day["first"]="Sunday"
        day[2]="Monday"
        day["second"]="Monday"
        day[4]="Wednesday"
        day["fourth"]="Wednesday"
        day[3]="Tuesday"
        day["third"]="Tuesday"
        for (i in day)
        {
           print i ORS day[i]
        }
}'
 

Улучшенная версия awk : Также вам нужно использовать 2 оператора для одного и того же значения, вы можете определить их одним способом назначения. Даже с разными индексами, имеющими одинаковые значения, это должно работать, что сэкономит несколько строк кода 🙂

 awk '
BEGIN{
        day[1]=day["first"]="Sunday"
        day[2]=day["second"]="Monday"
        day[4]=day["fourth"]="Wednesday"
        day[3]=day["third"]="Tuesday"
        for (i in day)
        {
            print i OFS day[i]
        }
}'
 

Комментарии:

1. для объединения заданий, т. е. day[1]=day["first"]="Sunday"

Ответ №2:

Менее подробный способ сделать это-разделить входные строки, например:

 awk -v days='Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday' 
    -v cardinal='First,Second,Third,Fourth,Fifth,Sixth,Seventh' '
BEGIN { 
  split(days,     days_ar,     /,/)
  split(cardinal, cardinal_ar, /,/)
  for (i=1; i<=7; i  ) 
    print cardinal_ar[i] " = " days_ar[i]
}' | column -t
 

Выход:

 First    =  Monday
Second   =  Tuesday
Third    =  Wednesday
Fourth   =  Thursday
Fifth    =  Friday
Sixth    =  Saturday
Seventh  =  Sunday
 

Комментарии:

1. Или n = split("first Sunday second Monday third Tuesday fourth Wednesday",tmp); for (i=1; i<n; i =2) { day[i] = day[tmp[i]] = tmp[i 1] } .

Ответ №3:

Огромное спасибо всем тем, кто откликнулся на мой призыв о помощи.

Я выбрал первый ответ, потому что мне интересно выяснить причину, по которой значения массива не печатались. RavinderSingh13 правильно определил причину, которая была связана с использованием $ с переменной i. Я ошибочно рассматривал Awk как сценарий оболочки. Ниже приведен код, который напечатал значения массива без включения переменной $ :

 awk '
BEGIN{
        day[1]=day["first"]="Sunday"
        day[2]=day["second"]="Monday"
        day[3]=day["third"]="Tuesday"
        day[4]=day["fourth"]="Wednesday"
        for (i in day)
        {
            print i,day[i]
        }
}'
 

Один интересный момент, который я узнал из сценариев Awk, заключается в том, что всегда будет выполняться только раздел BEGIN, с/без чтения входных файлов. С другой стороны, основной / КОНЕЧНЫЙ / оба раздела не будут выполняться, если оператор Awk не сопровождается по крайней мере входным файлом.