在段落内对行进行排序

时间:2016-03-09 19:13:34

标签: sorting awk sed

我需要更改文本文件中段落行的顺序,其中每个段落都有这种结构:

<body>blah blah</body>
<date>some date</date>
<user>some name</user>

我需要<user>some name</user>行作为每个段落中的第一行。即:

<user>some name</user>
<body>blah blah</body>
<date>some date</date>

如何在awk,sed等中完成此操作?

5 个答案:

答案 0 :(得分:0)

awk救援!

假设段落用一个或多个空行分隔,你可以这样做

$ awk 'BEGIN{RS=""; OFS=FS="\n"} {for(i=1;i<=NF;i++)
                                    if($i~/user/) {$1=$i OFS $1;
                                                   $i=""}}1' text

<user>some name</user>
<body>blah blah</body>
<date>some date</date>

<user>some name</user>
<body>blah blah</body>
<date>some date</date>

<user>some name</user>
<body>blah blah</body>
<date>some date</date>

你可以微调模式&#34;用户&#34;为了更准确的匹配,但适用于样本输入。

答案 1 :(得分:0)

Perl可以对段落中的行进行自定义排序

perl -00 -F'\n' -lane '
  print 
    join "\n", 
    sort {
      if    ($a =~ /<user>/) { -1 }
      elsif ($b =~ /<user>/) { +1 }
      else                   { $a cmp $b }
    }
    @F
' file

注意:

  • -00在段落中读取文件(由一个或多个空行分隔)
  • -F'\n'使用换行符作为字段分隔符,-a将段落的行拆分为perl数组@F
  • 自定义排序块首先排序<user>行,然后排序所有其他行。

one-liner-ized:

perl -00 -F'\n' -lape'$_=join"\n",sort{$a=~/<user>/?-1:$b=~/<user>/?1:$a cmp $b}@F' file

答案 2 :(得分:0)

使用sed:

sed '/<body>/{:a;N;/<user>/!ba};s/\(.*\)\n\(<user>.*\)/\2\n\1/' file

答案 3 :(得分:0)

以下假设<user>...</user>片段单独出现在一行上,除了这些<user>行之外,其他行不应重新排序。否则它非常强大,高效且适应性强。

awk '
  function p(  i) { for(i=0;i<n;i++) print s[i]; n=0; }
  /<user>/ {print; p(); next;}
  NF==0 {p(); print; next;}
  {s[n++]=$0}
  END { p() }'

答案 4 :(得分:0)

这可能就是你所需要的:

$ awk -F'[<>]' -v OFS='\n' '{a[$2]=$0} !(NR%3){print a["user"], a["body"], a["date"]}' file
<user>some name</user>
<body>blah blah</body>
<date>some date</date>

这仅仅取决于您尚未向我们展示的输入文件部分中的内容。