Я хочу преобразовать:
A,p
B,q
C,r
D,s
В:
A,p,q
B,q,r
C,r,s
Используя sed
.
Я подозреваю, что sed
не для этого (и другие могут знать, как сделать это намного лучше с sed
), но здесь идет речь:
$ sed '2,$ s/.$/&,&/' file | sed -r ':a;N;s/\n(.)(,?.?)(,.)$/\3\n\1\2/;ta' | sed '$d'
A,p,q
B,q,r
C,r,s
sed '2,$ s/.$/&,&/'
означает дублирование последнего символа во всех строках, кроме первой, с добавлением запятой:
2,$
со 2-й строки и далее s/old/new/
заменяют old
с new
.$
последним символом &
совпавшим шаблоном sed -r ':a;N;s/\n(.)(,?.?)(,.)$/\3\n\1\2/;ta;'
означает, что последний символ следует брать после каждой строки после первый и вставьте его в конец предыдущей строки:
-r
используйте метку ERE :a
: выполните отсюда ;
разделяет команды N
считывает следующую строку в пространство шаблона, поэтому мы можем использовать \n
для представления новых строк в шаблоне (.)
сохранить один символ для последующего использования ?
ноль или один из предшествующих символов $
конец строки \1
ссылка на сохраненный шаблон ta
, если последний Команда s
выполнена успешно, перейдите к :a
и выполните цикл снова $d
Удалите последнюю строку Если в вашем файле нет только одного символа между запятые, вы не сможете использовать очень простое регулярное выражение выше. Вот версия, которая работает, если файл разделен запятой. Например, учитывая
January,apple
February,pear
March,kiwi
April,mango
Вы можете сделать это, что также работает, если там есть только один символ, конечно же скрипты
$ sed '2,$ s/[^,]*$/&,&/' file | sed -r ':a;N;s/\n([^,]*)(,?[^,]*)(,[^,]*)$/\3\n\1\2/;ta;' | sed '$d'
January,apple,pear
February,pear,kiwi
March,kiwi,mango
sed
могут быть написано в несколько строк. Я не могу утверждать, что это значительно улучшает удобочитаемость;) но он может быть более переносимым, поскольку существуют ограничения на использование ;
в не-GNU версиях sed
:
sed '2,$ s/[^,]*$/&,&/' file |
sed -r '{:a
N
s/\n([^,]*)(,?[^,]*)(,[^,]*)$/\3\n\1\2/
ta}' |
sed '$d'
[^,]*
означает ноль или более символов, которые не являются запятыми.
Вот способ сделать это за один вызов sed:
sed -nE '$!{:a;N;s/(.*)\n(.*)(,[^,]*$)/\1\3\n\2\3/;P;D;ba;}' file
A,p,q
B,q,r
C,r,s
Структура :a;N;...P;D;ba
по существу поддерживает двухстрочный буфер, внутри которого мы можем разделите поля и скопируйте / переместите группы символов вокруг:
$!{ # For any line except the last
:a # Enter a loop:
N # Append the following line, after a newline
s/(.*)\n(.*)(,[^,]*)$/\1\3\n\2\3/ # Capture (1) up to the newline,
# (2) from the newline to the last comma,
# and (3) everything else into groups and
# copy group 3 before the newline
P # Print everything up to the newline
D # Delete everything up to the newline,
# ready for the next iteration
ba
}
Обратите внимание, что использование расширенного регулярного выражения -E
(или -r
) не является обязательным - оно просто уменьшает количество экранирования, которое необходимо.