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

use*_*123 5 awk sed

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

#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]
Run Code Online (Sandbox Code Playgroud)

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

我想我想做的是:

  1. 将每组三条线连接成一条线,每条线之间有一个分隔符
  2. 使用sort -k3,3对行进行排序
  3. 然后用分离的空白行重新组装3行结构
  4. 写入文件

我的预期输出看起来像这样:

#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]
Run Code Online (Sandbox Code Playgroud)

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

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

任何和所有的帮助非常感谢.

Håk*_*and 5

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

awk -f sort.awk input.txt
Run Code Online (Sandbox Code Playgroud)

这里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"
    }
}
Run Code Online (Sandbox Code Playgroud)

生产:

#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]
Run Code Online (Sandbox Code Playgroud)

  • 这个awk脚本非常防弹,试图打破它的几个方面 - 似乎到目前为止似乎.非常感谢你的解决方案.为了理解这个逻辑,我需要在一段时间内反对它.非常感谢你. (2认同)

Eta*_*ner 2

你的想法似乎是一个足够简单的方法。这似乎对我的测试数据有用。不过,它确实添加了额外的空白行,而且我目前没有足够的注意力来解决这个问题。

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