AWK слияние двух пересекающихся строк файлов

и спасибо, что нашли минутку для чтения, на данный момент я пытаюсь закончить и отшлифовать небольшую радиостанцию ​​с помощью icecast, на самом деле все уже работает.

однако есть программа под названием ezstream, которая просто транслирует музыку в icecast, когда никого нет в прямом эфире, это самый распространенный автодиджей, использующий плейлисты.

указанный плейлист может воспроизвести один раз, и программа закроется, и это именно то, что я хочу здесь использовать, мне удалось автоматически создать два разных плейлиста, один со всей музыкой, а другой с рекламой, джинглами и звуковыми байтами, и в основном они просто список файлов, хранящихся на компьютере. как следующее, очевидно, у них есть имена и прочее.

это будет плейлист1

/home/mp3/albums/album1/title1.mp3

/home/mp3/albums/album1/title2.mp3

/home/mp3/albums/album1/title3.mp3

/home/mp3/albums/album1/title4.mp3

/home/mp3/albums/album1/title5.mp3

/home/mp3/albums/album2/title1.mp3

/home/mp3/albums/album2/title2.mp3

/home/mp3/albums/album2/title3.mp3

/home/mp3/albums/album2/title4.mp3

/home/mp3/albums/album2/title5.mp3

плейлист2 очень похож, но содержит только рекламу, поэтому выглядит так

/home/mp3/commercials/commercial1.mp3

/home/mp3/commercials/commercial2.mp3

/home/mp3/commercials/commercial3.mp3

/home/mp3/commercials/commercial4.mp3

/home/mp3/commercials/commercial5.mp3

та часть, где я критически застрял, заключается в слиянии тех, что в соотношении 2: 1 или 3: 1 (если бы вы могли помочь мне с обоими кодами, это тоже было бы здорово).

конечный результат должен выглядеть примерно так

/home/mp3/albums/album1/title1.mp3

/home/mp3/albums/album1/title2.mp3

/home/mp3/commercials/commercial1.mp3

/home/mp3/albums/album1/title3.mp3

/home/mp3/albums/album1/title4.mp3

/home/mp3/commercials/commercial2.mp3

/home/mp3/albums/album1/title5.mp3

/home/mp3/albums/album2/title1.mp3

/home/mp3/commercials/commercial2.mp3

и так до тех пор, пока оба файла не будут полностью объединены, пока мне удалось найти только этот код, но он почему-то не работает, выдает ошибки, связанные с синтаксисом и отсутствием символа ‹.

АВК-код:

awk ‘FNR==NR{

song[FNR]=$0; 
next 
}

{

print song[FNR+line];line++;

print song[FNR+line]

print $0

}’ playlist1.m3u playlist2.m3u

все это надо вывести в третий файл скажем mergedplaylists.m3u

я не создавал этот код, хотя я пытался с ним возиться какое-то время, одна вещь, которая мне не очень ясна, это то, почему там написано «песня», можно ли ее изменить на что-то другое? сказать "альбом"?

код вообще не работает, ничего не пишет в выходной файл (и я не знаю, правильно ли это).

я надеюсь, что кто-то может помочь мне с конкретным случаем, AWK кажется полезным, но он очень загадочный, и я нахожу много проблем, чтобы понять его...

еще раз спасибо


person Rex    schedule 05.04.2013    source источник
comment
Синтаксическая проблема с этим кодом заключается в использовании прямой галочки (`) вместо обратной галочки (') в качестве первого символа awk-скрипта. Слово song — это просто имя переменной, используемое для обозначения массива — вы можете использовать любое слово для имени переменной.   -  person Ed Morton    schedule 05.04.2013


Ответы (1)


Это поставит 2 песни перед каждой рекламой:

awk '
FNR==NR{ song[++numSongs]=$0; next }
{
   for (i=1;i<=2;i++)
      print song[++songNr]
   print
}
songNr == numSongs { exit }
' playlist1.m3u playlist2.m3u

Измените «2» на «3» или что-то еще, как вы считаете нужным.

Альтернативная реализация на основе комментариев ниже:

$ cat tst.awk
BEGIN{ interval = (interval ? interval : 3) }

NR==FNR { songs[++numSongs] = $0; next }

{ commercials[++numCommercials] = $0 }

END {
    for (songNr=1; songNr<=numSongs; songNr++) {

        print songs[songNr]

        if ( !( songNr % interval) && (++commercialNr in commercials) )
            print commercials[commercialNr]

    }

}
$
$ cat songs.txt
/home/mp3/albums/album1/title1.mp3
/home/mp3/albums/album1/title2.mp3
/home/mp3/albums/album1/title3.mp3
/home/mp3/albums/album1/title4.mp3
/home/mp3/albums/album1/title5.mp3
/home/mp3/albums/album2/title1.mp3
/home/mp3/albums/album2/title2.mp3
/home/mp3/albums/album2/title3.mp3
/home/mp3/albums/album2/title4.mp3
/home/mp3/albums/album2/title5.mp3
$
$ cat commercials.txt
/home/mp3/commercials/commercial1.mp3
/home/mp3/commercials/commercial2.mp3
/home/mp3/commercials/commercial3.mp3
/home/mp3/commercials/commercial4.mp3
/home/mp3/commercials/commercial5.mp3
$
$ awk -f tst.awk songs.txt commercials.txt
/home/mp3/albums/album1/title1.mp3
/home/mp3/albums/album1/title2.mp3
/home/mp3/albums/album1/title3.mp3
/home/mp3/commercials/commercial1.mp3
/home/mp3/albums/album1/title4.mp3
/home/mp3/albums/album1/title5.mp3
/home/mp3/albums/album2/title1.mp3
/home/mp3/commercials/commercial2.mp3
/home/mp3/albums/album2/title2.mp3
/home/mp3/albums/album2/title3.mp3
/home/mp3/albums/album2/title4.mp3
/home/mp3/commercials/commercial3.mp3
/home/mp3/albums/album2/title5.mp3
$
$ awk -v interval=1 -f tst.awk songs.txt commercials.txt
/home/mp3/albums/album1/title1.mp3
/home/mp3/commercials/commercial1.mp3
/home/mp3/albums/album1/title2.mp3
/home/mp3/commercials/commercial2.mp3
/home/mp3/albums/album1/title3.mp3
/home/mp3/commercials/commercial3.mp3
/home/mp3/albums/album1/title4.mp3
/home/mp3/commercials/commercial4.mp3
/home/mp3/albums/album1/title5.mp3
/home/mp3/commercials/commercial5.mp3
/home/mp3/albums/album2/title1.mp3
/home/mp3/albums/album2/title2.mp3
/home/mp3/albums/album2/title3.mp3
/home/mp3/albums/album2/title4.mp3
/home/mp3/albums/album2/title5.mp3
$
$ awk -v interval=2 -f tst.awk songs.txt commercials.txt
/home/mp3/albums/album1/title1.mp3
/home/mp3/albums/album1/title2.mp3
/home/mp3/commercials/commercial1.mp3
/home/mp3/albums/album1/title3.mp3
/home/mp3/albums/album1/title4.mp3
/home/mp3/commercials/commercial2.mp3
/home/mp3/albums/album1/title5.mp3
/home/mp3/albums/album2/title1.mp3
/home/mp3/commercials/commercial3.mp3
/home/mp3/albums/album2/title2.mp3
/home/mp3/albums/album2/title3.mp3
/home/mp3/commercials/commercial4.mp3
/home/mp3/albums/album2/title4.mp3
/home/mp3/albums/album2/title5.mp3
/home/mp3/commercials/commercial5.mp3
$
$ awk -v interval=4 -f tst.awk songs.txt commercials.txt
/home/mp3/albums/album1/title1.mp3
/home/mp3/albums/album1/title2.mp3
/home/mp3/albums/album1/title3.mp3
/home/mp3/albums/album1/title4.mp3
/home/mp3/commercials/commercial1.mp3
/home/mp3/albums/album1/title5.mp3
/home/mp3/albums/album2/title1.mp3
/home/mp3/albums/album2/title2.mp3
/home/mp3/albums/album2/title3.mp3
/home/mp3/commercials/commercial2.mp3
/home/mp3/albums/album2/title4.mp3
/home/mp3/albums/album2/title5.mp3

Вот авк:

BEGIN{ interval = (interval ? interval : 3) }

NR==FNR { songs[++numSongs] = $0; next }

{ commercials[++numCommercials] = $0 }

END {
    for (songNr=1; songNr<=numSongs; songNr++) {

        print songs[songNr]

        if ( !(songNr % interval) && (++commercialNr <= numCommercials) )
            print commercials[commercialNr]

    }

}

Вот C-подобный псевдокод:

void main() {

    FILE *filep;
    char *line;

    char *songs[1000];
    char *commercials[1000];

    int FNR = 0;
    int NR = 0;
    int interval = 0;
    int numSongs = 0;
    int numCommercials = 0;
    int songNr = 0;
    int commercialNr = 0;
    int argNr = 0;

    /* BEGIN */
    if (ARGV[++argNr] == "interval") {
         interval = ARGV[++argNr];
    }
    interval = (interval ? interval : 3);

    for (++argNr;argNr<=ARGC;argNr++) {
       filep = ARGV[argNr];
       FNR = 0;
       while ( fgets(line,filep) > 0 ) {
          NR++;
          FNR++;

          if (NR == FNR) { songs[++numSongs] = line; continue; }

          commercials[++numCommercials] = line;

       }
    }

    /* END */
    for (songNr=1; songNr<=numSongs; songNr++) {

        printf("%s\n",songs[songNr]);

        if ( !(songNr % interval) && (++commercialNr <= numCommercials) )
                printf("%s\n",commercials[commercialNr]);
        }

    }

    return;
}

Единственное изменение, которое я внес в сценарий awk для простоты сравнения, заключалось в удалении оператора «in», для которого нет четкого эквивалента C.

Надеюсь, это поможет прояснить, что делает скрипт awk.

person Ed Morton    schedule 05.04.2013
comment
я получил синтаксическую ошибку на последнем отпечатке, имеет ли значение, если скрипт содержит слово Song, хотя нет файлов, называемых таким образом? (кроме одного фактического, /home/mp3/albums/The Best of/02 Song 2.mp3 (от Blur ehehehe) - person Rex; 05.04.2013
comment
Это не печать. Я скопировал/вставил ваш пример и подправил его, чтобы создать сценарий, который я разместил, но оказалось, что последний символ кавычки в вашем вопросе не был обычной кавычкой, отсюда и синтаксическая ошибка. Я исправил свой ответ. Имя переменной, используемое в скрипте, не имеет абсолютно ничего общего с именами полей, которые существуют вне скрипта. Единственные 2 имени файла, упомянутые выше, это playlist1.m3u и playlist2.m3u. - person Ed Morton; 05.04.2013
comment
извините, я просто не могу заставить его работать, я пытался набрать его в командной строке, не повезло, также вырезал и вставил в скрипт .sh (тот, который в настоящее время создает первые плейлисты, и это дает мне ошибку, также пробовал в сценарий оболочки сам по себе, чтобы увидеть, как он работает в одиночку, получил ошибку интерпретатора, поэтому я изменил его на #!usr/bin/awk и запустил его, я получил неопределенную ошибку регулярного выражения, я не считаю себя таким нубом, но эта штука awk действительно делает себя все труднее и труднее для меня - person Rex; 05.04.2013
comment
Вы почти наверняка делаете только одну фундаментальную вещь неправильно. Нам просто нужно выяснить, что это такое. Для начала: скопируйте/вставьте мой скрипт выше в свое окно и нажмите клавишу возврата. Теперь скопируйте / вставьте то, что вы сделали, и результат, который вы получили, в исходный вопрос выше, чтобы мы могли увидеть сообщение об ошибке. В случае, если вы используете Solaris, НЕ используйте /usr/bin/awk или /bin/awk, так как они оба старые, сломанные awk - вместо этого используйте /usr/xpg4/bin/awk или nawk. - person Ed Morton; 05.04.2013
comment
я просто переделал весь процесс копирования и вставки и он работает, мне пришлось немного подкрутить в конце, в основном для имен файлов и к моменту его окончания я просто добавил › playlist-final.m3u и команду для выполнения ezstream, это работает, однако я заметил кое-что, так как рекламы меньше, чем песен, плейлист будет только до тех пор, пока показываются рекламные ролики, то есть 3 рекламных ролика будут отображать только 6 песен, на самом деле это не имеет значения, так как список будет постоянно обновляться один раз ezstream завершит воспроизведение текущего и снова выберет песни случайным образом. - person Rex; 05.04.2013
comment
Если вы можете описать алгоритм, который вам нужен, по количеству песен и количеству рекламных роликов, я могу показать вам, как написать его в awk. - person Ed Morton; 05.04.2013
comment
так как количество песен будет постоянно меняться, так как они будут добавляться со временем, так же как и реклама, я полагаю, это было бы довольно бессмысленно, однако есть хорошая вещь, которую я заметил, все рекламные ролики будут проигрываться каждый раз, когда плейлист обновляется, и песни всегда будут разными, потому что исходный список воспроизведения1 и список воспроизведения2 проходят через сортировку -R playlist1.m3u › random-playlist1.m3u, поэтому они рандомизируются, а список воспроизведения1 фактически создается из серии отдельных списков воспроизведения, которые создаются вручную при альбом заливается через кат *.m3u|grep -v рекламные ролики › playlist1.m3u - person Rex; 05.04.2013
comment
ОК, я добавил альтернативный способ реализации, с которым вам будет проще работать и изменять при необходимости. При таком подходе вы можете динамически вычислять значение интервала на основе numSongs и numCommercials, когда вы входите в раздел END, чтобы вы автоматически всегда использовали все свои песни плюс все свои рекламные ролики, если это желательно. Наслаждаться! - person Ed Morton; 05.04.2013
comment
это безумие, большое спасибо, я честно не могу заставить себя понять awk, это слишком загадочно, но эй, ты понял, еще раз спасибо и приятного дня: D - person Rex; 06.04.2013
comment
Хм, я не могу представить, что загадочного в этом сценарии. Я добавлю C-подобный перевод псевдокода, чтобы посмотреть, поможет ли это. - person Ed Morton; 06.04.2013