我需要更改文本文件中段落行的顺序,其中每个段落都有这种结构:
<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等中完成此操作?
答案 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>
这仅仅取决于您尚未向我们展示的输入文件部分中的内容。