使用awk和/或sed按字母顺序对文件中的行进行排序

时间:2013-11-27 19:04:22

标签: sed awk

我有一个数百行格式的文件:

#blah
RewriteCond %{HTTP_HOST} www.blah.com [NC]
RewriteRule ^/xyz(|/)$ http://www.blah.com/404.html [R=301,L,NC]

#xblah
RewriteCond %{HTTP_HOST} www.blah.com [NC]
RewriteRule ^/hkf(|/)$ http://www.blah.com/404.html [R=301,L,NC]

#ablah
RewriteCond %{HTTP_HOST} www.blah.com [NC]
RewriteRule ^/abc/.*(|/)$ http://www.blah.com/404.html [R=301,L,NC]

我想在awk / sed中创建一个脚本,使用每组文本第三行中的第二个参数对该文件进行字母顺序排列。在这个文件的情况下,它是“abc”,“hkf”或“xyz”,可以是任何东西 - 它们是在这个apache重定向文件中创建的重定向。

我认为我想做的是:

  1. 将每组三行连接成一行,每行之间有一个分隔符
  2. 使用sort -k3,3
  3. 对行进行排序
  4. 然后用分离的空白行重新组装3行结构
  5. 写入文件
  6. 我的预期输出如下:

    #ablah
    RewriteCond %{HTTP_HOST} www.blah.com [NC]
    RewriteRule ^/abc/.*(|/)$ http://www.blah.com/404.html [R=301,L,NC]
    
    #xblah
    RewriteCond %{HTTP_HOST} www.blah.com [NC]
    RewriteRule ^/hkf(|/)$ http://www.blah.com/404.html [R=301,L,NC]
    
    #blah
    RewriteCond %{HTTP_HOST} www.blah.com [NC]
    RewriteRule ^/xyz(|/)$ http://www.blah.com/404.html [R=301,L,NC]
    

    这有意义吗?有一个更好的方法吗?

    P.S。我的目的是使脚本可移植,以便它可以在这个结构的几个文件上使用。在建议解决问题的代码时,请尽可能地将其拼写为像我这样的新职级,以便开始了解如何有效地解决这个问题,并能够扩展最终结果。

    任何和所有帮助都非常感激。

3 个答案:

答案 0 :(得分:5)

你可以在Gnu Awk中完成整个操作:

awk -f sort.awk input.txt

其中sort.awk

BEGIN {
    RS=""
}
{
    match($0,/RewriteRule \^\/(.*)\(\|/,a)
    key[NR]=a[1] "\t" NR
    block[NR]=$0
}

END {
    asort(key)
    for (i=1; i<=NR; i++) {
        split(key[i],a,"\t")
        print block[a[2]]
        printf "\n"
    }
}

产地:

#ablah
RewriteCond %{HTTP_HOST} www.blah.com [NC]
RewriteRule ^/abc/.*(|/)$ http://www.blah.com/404.html [R=301,L,NC]

#xblah
RewriteCond %{HTTP_HOST} www.blah.com [NC]
RewriteRule ^/hkf(|/)$ http://www.blah.com/404.html [R=301,L,NC]

#blah
RewriteCond %{HTTP_HOST} www.blah.com [NC]
RewriteRule ^/xyz(|/)$ http://www.blah.com/404.html [R=301,L,NC]

答案 1 :(得分:2)

你的想法似乎很简单。这似乎对我的测试数据有用。它确实增加了额外的空白行,而我现在还没有足够的重点来解决这个问题。

awk '/^#/,/^$/ {printf "%s\0",$0} /^$/ {print ""} END {print ""}' 20250937.input | sort -t'\0' -k3,3 | tr '\0' '\n'
  1. 对于/ ^#/和/ ^ $ /之间的所有行,使用null而不是换行符终止符打印出行。
  2. 当我们看到空行时也会打印出换行符。
  3. 确保我们的输出以换行符终止。
  4. 按字段排序。
  5. 将空值转换回换行符。

答案 2 :(得分:1)

一些sed版本:

sed -n '/^#/{N;h;n;H;x;s/\n/XnlX/g;x;s!.*\^/\([a-z]*\).*!\1!;G;s/\n/ /;p}' input \
         | sort |  sed 's/[^ ]* //;s/$/\n/;s/XnlX/\n/g'

产地:

 #ablah 
 RewriteCond %{HTTP_HOST} www.blah.com [NC] 
 RewriteRule ^/abc/.*(|/)$ http://www.blah.com/404.html [R=301,L,NC]

 #xblah 
 RewriteCond %{HTTP_HOST} www.blah.com [NC] 
 RewriteRule ^/hkf(|/)$ http://www.blah.com/404.html [R=301,L,NC]

 #blah 
 RewriteCond %{HTTP_HOST} www.blah.com [NC] 
 RewriteRule ^/xyz(|/)$ http://www.blah.com/404.html [R=301,L,NC]