sed выравнивает все строки до последней строки в файле Bash-скрипта

344
Teja554

У меня есть файлы с нижними строками

Dev_Campaign_1873.rpm Dev_Campaign_1987.rpm Dev_Campaign_9876.rpm http://52.30.241.107:8081/artifactory/api/storage/adifact 

Попытка получить вывод в файл, как показано ниже, используя sed или любую другую команду

http://52.30.241.107:8081/artifactory/api/storage/adifact/Dev_Campaign_1873.rpm http://52.30.241.107:8081/artifactory/api/storage/adifact/Dev_Campaign_1987.rpm http://52.30.241.107:8081/artifactory/api/storage/adifact/Dev_Campaign_9876.rpm 
0

1 ответ на вопрос

0
Stas Bushuev

Попробуйте этот скрипт: он очень хакерский и основан на двух вещах: текст не содержит символ '|' и только последняя строка начинается с 'http:'.

:again ${ s/\n/|/g # to include first part too s/^/|/ :next # modify last non processed part s/\(.*\)|\([^|]\+\)|\(.*\)\(http:.*\)/\1|\4\/\2\n\3\4/ t next # remove unneeded guard s/^|// # remove prefix s/\(.*\n\)\([^\n]\+\)/\1/ b end } N b again :end 

Как это работает?

Предположим, что у нас есть этот вход:

aaa bbb http://zzz 

Во-первых, скрипт объединяет все строки из файла во внутренний буфер:

:again ${ # Here internal buffer will be processed b end } N b again :end 

Это очень распространенный шаблон в моих сценариях, когда sed не может обрабатывать текст построчно, а ввод не очень велик. Начиная с первой строки, скрипт не прерывается и просто читает следующую строку ('N') в буфер до конца.

Когда он получает последнюю строку ('$'), он может обрабатываться дальше. И когда это закончено, это останавливается ('конец'). Нельзя использовать дифинитную метку для достижения цели, просто «b» тоже подойдет, но я предпочитаю ясность.

Итак, теперь во внутреннем буфере находится этот текст:

aaa\nbbb\nhttp://zzz 

Далее он разделяет строки с символом '|' вместо '\ n':

s/\n/|/g # to include first part too s/^/|/  |aaa|bbb|http://zzz 

Затем он пытается найти эту модель

...|text|.....http://... 

и изменить это на это

...|http://...text\n.....http://... 

Из-за жадности используемого регулярного выражения, подстановка происходит от конца до начала строки, на каждом шаге удаляется один символ '|':

Initial state of buffer: |aaa|bbb|http://zzz  After first step: |aaa|http://zzz/bbb\nhttp://zzz  After second step: |http://zzz/aaa\nhttp://zzz/bbb\nhttp://zzz 

Цикл был организован с помощью команды 't next'. Он переходит к метке «следующий», если последняя замена прошла успешно.

Затем он удаляет ненужную охрану '|' в начале строки:

s/^|//  http://zzz/aaa\nhttp://zzz/bbb\nhttp://zzz 

И последняя строка:

s/\(.*\n\)\([^\n]\+\)/\1/  http://zzz/aaa\nhttp://zzz/bbb 

Итак, когда он, наконец, напечатает буфер, вы получите это:

http://zzz/aaa http://zzz/bbb