【问题标题】:AWK merging of two files intercrossing linesAWK合并两个文件交叉行
【发布时间】:2013-04-05 17:46:23
【问题描述】:

感谢您抽出时间阅读本文,此时我正在尝试使用 icecast 完成和润色一个小型广播电台,实际上一切都已经开始工作了。

但是有一个名为 ezstream 的程序,它只是在无人直播时将音乐流式传输到 icecast,它是最常见的 autodj,使用播放列表。

说播放列表可以播放一次然后程序关闭,这正是我想在这里利用的,我设法自动创建了两个不同的播放列表,一个包含所有音乐,另一个包含广告、叮当声和声音字节,以及基本上它们只是存储在计算机上的文件列表。像下面这样,显然他们有名字和东西。

这将是播放列表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

playlist2 非常相似,但它只包含广告,所以看起来像这样

/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 代码:

awk ‘FNR==NR{

song[FNR]=$0; 
next 
}

{

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

print song[FNR+line]

print $0

}’ playlist1.m3u playlist2.m3u

所有这些都应该输出到第三个文件,比如mergedplaylists.m3u

我没有创建该代码,尽管我已经尝试摆弄了一段时间,但我不太清楚的一件事是为什么它在那里说“歌曲”,可以将其更改为其他内容吗?说“专辑”?

代码根本不起作用,也没有在输出文件中写入任何内容(我也不知道它是否正确)。

我希望 some1 可以帮助我处理特定情况,AWK 似乎很有帮助,但它非常神秘,我发现很多问题要理解它......

再次感谢您

【问题讨论】:

  • 该代码的语法问题是使用正引号 (`) 而不是反引号 (') 作为 awk 脚本的第一个字符。 “song”这个词只是一个用于命名数组的变量名——你可以使用任何你喜欢的词作为变量名。

标签: awk playlist gawk


【解决方案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”或您认为合适的任何内容。

下面基于cmets的替代实现:

$ 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

这里是 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 <= 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 脚本所做的唯一更改是删除了没有明确的 C 等效项的“in”运算符。

希望这有助于澄清 awk 脚本在做什么。

【讨论】:

  • 我在最后一次打印时遇到语法错误,脚本是否包含单词“Song”是否有关系,尽管没有以这种方式调用的文件? (除了一个实际的,/home/mp3/albums/The Best of/02 Song 2.mp3(by Blur ehehehe)
  • 这不是“打印”。我复制/粘贴了您的示例并对其进行了调整以创建我发布的脚本,但事实证明您问题中的最后一个引号字符不是正常的引号,因此出现了语法错误。我确定了我的答案。脚本中使用的变量名与脚本之外存在的任何文件名完全无关。上面提到的唯一2个文件名是playlist1.m3u和playlist2.m3u
  • 对不起,我不能让它工作,我尝试在命令行上输入它,没有运气,也剪切并粘贴在 .sh 脚本中(当前创建第一个播放列表的那个,它给出我一个错误,也尝试在 shell 脚本中看到它单独工作,得到解释器错误,所以我将它更改为 #!usr/bin/awk 并运行它,我得到未确定的正则表达式错误,我不认为自己是这样的菜鸟,但是这个 awk 东西真的让我越来越难了
  • 您几乎可以肯定只做错了一件基本的事情。我们只需要弄清楚那是什么。开始:将上面的脚本复制/粘贴到您的窗口中,然后按回车键。现在复制/粘贴您所做的以及您在上面的原始问题中得到的输出,以便我们可以看到错误消息。如果您使用的是 Solaris,请不要使用 /usr/bin/awk 或 /bin/awk,因为它们都是旧的、损坏的 awk - 请改用 /usr/xpg4/bin/awk 或 nawk。
  • 我只是重做了所有的复制粘贴过程,它可以工作,我不得不在最后稍微扭曲一下,主要是为了文件名,当它完成时,我刚刚添加了一个 > playlist-final.m3u以及执行 ezstream 的命令,它可以工作,但是我注意到一些事情,因为广告比歌曲少,只要显示广告,播放列表就会出现,这意味着 3 个广告只会弹出 6 首歌曲,这并不重要,因为一旦 ezstream 播放完当前歌曲,列表将不断刷新并再次随机选择歌曲
猜你喜欢
  • 1970-01-01
  • 2016-07-30
  • 2018-01-21
  • 1970-01-01
  • 1970-01-01
  • 2020-06-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多