Как поменять местами слова после определенного слова, которое может быть в одной строке или в разных строках с помощью sed? - PullRequest
0 голосов
/ 02 мая 2019

У меня есть файл, где начинается строка:

OCCUPY 12 EVERY PIC 32(12).     SUNNY 
OCCUPY 45 EVERY PIC X(21).      SUNNY

и некоторые строки могут быть разбиты на две строки:

1      OCCUPY 12 EVERY PIC 32(12).    SUNNY
2              OCCUPY 45 EVERY        SUNNY 
3                   PIC X(21).        SUNNY

И желаемый результат:

PIC 32(12) OCCUPY 12 EVERY.    SUNNY
PIC X(21) OCCUPY 45 EVERY.     SUNNY 

Итак, мне нужно собрать разделенные строки в один ряд и поменять местами слова. Итак, для тех, кто находится в одном ряду, я использую команду:

sed 's/\(OCCUPY.*EVERY\) *\(PIC *[^ }*\)\./\2 \1./'
sed -Ez 's/(OCCUPY)\s+([0-9]+)\s+(EVERY)\s+(PIC)\s+([^)]+\))/\4 \5 \1 \2 \3/g'

Эти команды работают, но только если строка находится в одной строке, а также она сдвигает слово SUNNY, а точка находится на расстоянии одного пробела. Слово СОЛНЕЧНОЕ должно быть в одном и том же поле. Итак, неверный вывод:

PIC 32(12) OCCUPY 12 EVERY.     SUNNY
PIC X(21) OCCUPY 45 EVERY .   SUNNY 

Любая помощь будет оценена !!

Ответы [ 2 ]

1 голос
/ 02 мая 2019

С GNU sed для -E, -z и \s сокращение для [[:space:]]:

$ sed -Ez 's/(OCCUPY\s+[0-9]+\s+EVERY)\s+(PIC\s+[^)]+\))/\2 \1/g' file
PIC 32(12) OCCUPY 12 EVERY.
PIC X(21) OCCUPY 45 EVERY.

и, если каждая строка соответствует этому шаблону из пробелов / непробельных строк, вы можете уменьшить ее до:

$ sed -Ez 's/((\S+\s+){2}\S+)\s+(\S+\s+\S+\))/\3 \1/g' file
PIC 32(12) OCCUPY 12 EVERY.
PIC X(21) OCCUPY 45 EVERY.

или, если линия может быть разбита в любом пустом месте, а не только там, где показано в вашем примере:

$ sed -Ez 's/(OCCUPY)\s+([0-9]+)\s+(EVERY)\s+(PIC)\s+([^)]+\))/\4 \5 \1 \2 \3/g' file
PIC 32(12) OCCUPY 12 EVERY.
PIC X(21) OCCUPY 45 EVERY.

$ sed -Ez 's/(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+\))/\4 \5 \1 \2 \3/g' file
PIC 32(12) OCCUPY 12 EVERY.
PIC X(21) OCCUPY 45 EVERY.

Учитывая ваш обновленный ввод / вывод, скрипты все еще работают:

$ cat file
OCCUPY 12 EVERY PIC 32(12).     SUNNY
OCCUPY 45 EVERY
        PIC X(21).      SUNNY

$ sed -Ez 's/(OCCUPY\s+[0-9]+\s+EVERY)\s+(PIC\s+[^)]+\))/\2 \1/g' file
PIC 32(12) OCCUPY 12 EVERY.     SUNNY
PIC X(21) OCCUPY 45 EVERY.      SUNNY

$ sed -Ez 's/((\S+\s+){2}\S+)\s+(\S+\s+\S+\))/\3 \1/g' file
PIC 32(12) OCCUPY 12 EVERY.     SUNNY
PIC X(21) OCCUPY 45 EVERY.      SUNNY

$ sed -Ez 's/(OCCUPY)\s+([0-9]+)\s+(EVERY)\s+(PIC)\s+([^)]+\))/\4 \5 \1 \2 \3/g' file
PIC 32(12) OCCUPY 12 EVERY.     SUNNY
PIC X(21) OCCUPY 45 EVERY.      SUNNY

$ sed -Ez 's/(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+\))/\4 \5 \1 \2 \3/g' file
PIC 32(12) OCCUPY 12 EVERY.     SUNNY
PIC X(21) OCCUPY 45 EVERY.      SUNNY
0 голосов
/ 02 мая 2019

Это может сработать для вас (GNU sed):

sed -E '/OCCUPY/{:a;/ PIC/!{N;s/\n\s*//;ta};s/PIC/\n&/;s/(.*) \n([^.]*)/\2 \1/}' file

Это фокусируется на строках, которые содержат OCCUPY, а затем, если эта же строка также не содержит PIC, добавляет дополнительные строки (удаляя их новые строки) до тех пор, пока это не произойдет.

Используя введенную новую строку в качестве разделителя, он затем использует сопоставление с образцом, чтобы переместить строку в пространстве рисунка в требуемый формат.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...