AWK 3.1.7 - несколько циклов в одном for

Я пытаюсь отсортировать 2 массива со следующим кодом:

 n = asorti (pacben,pacsor)
 m = asorti (pacben2,pacsor2)

Мне нужно их рассортировать, желательно вместе. Я знаю, что я могу сделать каждый отдельно со следующим:

 n = asorti (pacben,pacsor)
for (p = 1;p <= n; p++) {
blah
}
 m = asorti (pacben2,pacsor2)
for (p2 =1;p2 <= m; p2++) {
blah
}

но когда я пытаюсь сделать следующее:

 n = asorti (pacben,pacsor)
 m = asorti (pacben2,pacsor2)
for (p = 1;p <= n;p++ && p2 = 1;p2 <= m;p2++) {
blah
}

Я получаю следующую ошибку:

awk: cmd. line:25:                         for (p = 1;p <= n;p++ && p2 = 1;p2 <= m; p2++) {
awk: cmd. line:25:                                                        ^ syntax error
awk: cmd. line:25:                         for (p = 1;p <= n;p++ && p2 = 1;p2 <= m; p2++) {
awk: cmd. line:25:                                                                      ^ syntax error

Любая помощь будет оценена по достоинству.


person glly    schedule 25.06.2016    source источник
comment
Не уверен, что понял вопрос. Вызова asorti достаточно для сортировки. Цикл предназначен для отображения или использования содержимого. Если вы хотите просмотреть оба массива вместе, вы можете использовать только один индекс (свободный p2) и будьте осторожны, так как один индекс может быть меньше другого.   -  person call me Steve    schedule 26.06.2016
comment
@callmeSteve, так как бы был написан цикл for? должен ли я использовать один и тот же veriable для обоих asorti? например. n=asorti(pacben,pacsor) n=asorti(pacben2,pacsor2) for (p=1;p<=n;p++)   -  person glly    schedule 26.06.2016


Ответы (2)


В C вы бы изменили:

for (p = 1;p <= n;p++ && p2 = 1;p2 <= m;p2++) {

в:

for (p = 1, p2 = 1; p <= n && p2 <= m; p1++, p2++) {

Это одно из стандартных применений оператора запятой. Однако оказывается, что awk не принимает оператор запятой.

Mac OS X (BSD) awk:

$ awk -v n=2 -v m=3 'BEGIN { for (p = 1, p2 = 1; p <= n && p2 <= m; p1++, p2++) print p1, p2}'
awk: syntax error at source line 1
 context is
    BEGIN { for (p = >>>  1, <<< 
awk: illegal statement at source line 1
awk: illegal statement at source line 1
$

ГНУ awk:

$ awk -v n=2 -v m=3 'BEGIN { for (p = 1, p2 = 1; p <= n && p2 <= m; p1++, p2++) print p1, p2}'
awk: cmd. line:1: BEGIN { for (p = 1, p2 = 1; p <= n && p2 <= m; p1++, p2++) print p1, p2}
awk: cmd. line:1:                   ^ syntax error
awk: cmd. line:1: BEGIN { for (p = 1, p2 = 1; p <= n && p2 <= m; p1++, p2++) print p1, p2}
awk: cmd. line:1:                                                    ^ syntax error
$

Спецификация POSIX для awk не включает оператор запятой в список операторов.

Вы можете использовать:

$ awk -v n=2 -v m=3 'BEGIN { for (p1 = p2 = 1; p1 <= n && p2 <= m; p1++ && p2++) print p1, p2}'
1 1
2 2
$

Это использует тот факт, что p1 и p2 инициализируются одним и тем же значением, и что оба p1 и p2 не равны нулю в части увеличения цикла.

person Jonathan Leffler    schedule 26.06.2016
comment
Удивительное спасибо, которое работает как шарм. никогда бы не подумал, что вы можете сделать это в операторе for. - person glly; 26.06.2016
comment
Подождите - вы НИКОГДА не напишете этот последний цикл, поскольку он эквивалентен гораздо более простому for (p = 1; p <= n && p <= m; p++) print p, p. См. stackoverflow.com/a/38038530/1745001. - person Ed Morton; 26.06.2016
comment
Да, @EdMorton; не было бы необходимости в двух машинах с контурным управлением, как написано. Я предполагаю, что в теле реального цикла есть что-то, что обрабатывает (инкрементирует или декрементирует, так что готов в противном случае настроить) индексы цикла отдельно. - person Jonathan Leffler; 26.06.2016
comment
Я подозреваю, что ОП просто думает, что ему нужно 2 переменных управления циклом, потому что у него 2 массива. - person Ed Morton; 26.06.2016

Будь проще. Существуют различные возможные решения в зависимости от того, что вы действительно хотите и что blah может сделать, но на основе вашего принятия @JonathanLeffer answer, это должно быть то, что вы хотите:

n = asorti (pacben,pacsor)
m = asorti (pacben2,pacsor2)
for (p = 1;p <= n && p <=m; p++) {
    blah
}

но также подумайте, как обрабатывать массивы разных размеров:

$ cat tst.awk
BEGIN{
    n = split("A C E",a)
    m = split("B D F G H",b)
    for (p=1;p<=n && p<=m;p++) {
        print a[p] ORS b[p]
    }
    for (;p <= (n > m ? n : m);p++) {
        print (n > m ? a[p] : b[p])
    }
}

$ awk -f tst.awk
A
B
C
D
E
F
G
H
person Ed Morton    schedule 26.06.2016
comment
Ах, это приятно знать. - person glly; 26.06.2016