2016-03-09 2 views
-1

мне нужно изменить порядок строк абзацев в текстовом файле, где каждый пункт имеет такую ​​структуру:Сортировка строк в пределах пунктов

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

мне нужна линия с <user>some name</user> быть первым один в каждом параграф. I.e .:

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

Как это сделать, в awk, sed и т. Д.?

+0

Как разделены параграфы? Являются ли ' ...' частями полностью на одной линии? – muru

+0

«paragraph» имеет особое значение для awk - это записи, разделенные одной или несколькими пустыми строками. Это то, что у вас есть? Добавьте вторую запись (блок строк), чтобы мы могли видеть, что отделяет их от вашего ввода. –

ответ

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> 

вы можете точно настроить шаблон «пользователь» для более точного матча, но работают для ввода образца.

+0

Работает отлично! Спасибо! –

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> во-первых, а все остальные строки лексически.

один вкладыш-роскопию:

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

Блестящий! Спасибо! –

0

С СЕПГ:

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

Отлично! Спасибо! –

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() }' 
+0

Это решение работает. Спасибо! –

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> 

Это зависит только от того, что находится в части входного файла, который вы не показали нам.

+0

Это работает, спасибо. Мне нравится его простота. Как я могу заставить пустую строку между абзацами?(извините, я не указал, что в моем исходном посте был один) –

+0

тривиально, но вы все еще не обновили свой пост, и вы уже выбрали ответ, так что удачи! –

+0

Спасибо, ред. Все предлагаемые решения, за исключением ваших, правильно интерпретируют понятие «абзац», поскольку «существует пустая строка, разделяющая группы строк», поэтому все они отлично работают для того, что мне нужно. Я здесь новичок, и поэтому я не понял, насколько грубый может получиться, если они не получат ответы «проголосовали», «понравились» или какие-то другие эго-повышающие тики, которые люди могут после онлайн. Приветствия. –

Смежные вопросы