Perl Multiline найти и заменить - PullRequest
       33

Perl Multiline найти и заменить

1 голос
/ 20 января 2012

Я пытаюсь использовать простой однострочный perl для следующего ввода:

@F7##########0/1
C4CTA6GCAAC56G67CTCA99C
+
b[[WZ56W]87X9HBB
@44FC6%%%%&&&&&&&1UP1
GTS4HY2IOMD3FCCA8DFLLLTG
+
]]^4YY23ZV\6`a8`^9^a

и т. Д.

Я бы хотел, чтобы мой вывод выглядел так:

@F7##########0/1
C4CTA6GCAAC56G67CTCA99C
+F7##########0/1
b[[WZ56W]87X9HBB
@44FC6%%%%&&&&&&&1UP1
GTS4HY2IOMD3FCCA8DFLLLTG
+44FC6%%%%&&&&&&&1UP1
]]^4YY23ZV\6`a8`^9^a

и т. Д.

Я хотел бы найти строку, начинающуюся с @, и сохранить (сгруппировать) остаток строки в $1.Затем я нахожу следующее вхождение + и добавляю $1 в конец этой строки.

Я пробовал perl -pi -e "s%^@(.*)$\1\n(.*)$\2\n(\+)$\3\n%$1\n$2\n\+$1%mg" file.txt, но после ^@(.*)$\1\n. * Я не могу ничего найти.1019 *

Конечно, есть работающий однострочник для этого.Однострочники Awk или Sed или tr приветствуются, но изменения в file.txt должны быть внесены в строку, так как file.txt велик, а запись в другой файл нежелательна.

Ответы [ 4 ]

3 голосов
/ 20 января 2012

К сожалению, awk не предлагает встроенных изменений, поэтому это может быть не то, что вам нужно. Но если вы это сделаете, то сработает следующее:

awk '/^@/{a=substr($0,2)}/^\+/{printf ("%s%s\n", $0,a);next}1' file > newfile

Обновление: Я предпринял попытку сделать то, что вы ищете, в sed, который допускает изменения in-file.

sed -i '/^@/{h};/^\+/{x;s/\(.\)\(.*\)/+\2/}' file

Пояснение:

  • /^@/{h}: Мы ищем строку, которая начинается со знака @, и когда мы ее находим, мы помещаем всю строку в hold space. Sed имеет два буфера, pattern space и hold space. Pattern space - это место, где происходит все действие. hold space позволяет нам временно хранить информацию, чтобы впоследствии мы могли предпринять какие-либо действия с ней.
  • /^\+/{x;...: Когда мы находим строку, начинающуюся с +, мы выполняем действие x над ней. Это означает, что мы извлекаем информацию из нашего hold space и помещаем обратно в pattern space. Как только мы это сделали, мы делаем простую замену.
  • ...s/\(.\)\(.*\)/+\2/: Это означает, что мы идентифицируем символы с помощью grouping. Поскольку перед нашей частью текста было @, что вам не нужно, мы выделяем этот символ, используя ., что означает любой символ. Мы также поместили все остальное в этой строке во вторую группу. Эти группы должны быть экранированы {поэтому вы видите \ (\) вместо just ()}. В разделе замены мы вставляем + и вторую группу. Помните, что в первой захваченной группе было только @. Нам просто нужна вторая группа, поэтому мы ссылаемся на нее с помощью \2 (обратная косая черта и номер группы, на которую вы хотите сослаться).

Тест для awk:

[jaypal:~/Temp] cat file
@F7##########0/1
C4CTA6GCAAC56G67CTCA99C
+
b[[WZ56W]87X9HBB
@44FC6%%%%&&&&&&&1UP1
GTS4HY2IOMD3FCCA8DFLLLTG
+
]]^4YY23ZV\6`a8`^9^a

[jaypal:~/Temp] awk '/^@/{a=substr($0,2)}/^\+/{printf ("%s%s\n", $0,a);next}1' file
@F7##########0/1
C4CTA6GCAAC56G67CTCA99C
+F7##########0/1
b[[WZ56W]87X9HBB
@44FC6%%%%&&&&&&&1UP1
GTS4HY2IOMD3FCCA8DFLLLTG
+44FC6%%%%&&&&&&&1UP1
]]^4YY23ZV\6`a8`^9^a

Тест для sed:

Вы можете использовать опцию -i для внесения изменений на месте. Следующее предназначено только для демонстрации, чтобы вы могли увидеть результат.

[jaypal:~/Temp] sed '/^@/{h};/^\+/{x;s/\(.\)\(.*\)/+\2/}' file
@F7##########0/1
C4CTA6GCAAC56G67CTCA99C
+F7##########0/1
b[[WZ56W]87X9HBB
@44FC6%%%%&&&&&&&1UP1
GTS4HY2IOMD3FCCA8DFLLLTG
+44FC6%%%%&&&&&&&1UP1
]]^4YY23ZV\6`a8`^9^a
2 голосов
/ 20 января 2012

Мои извинения.Я читаю ваш вопрос более внимательно и вижу, что вы хотите обрабатывать ваш файл построчно.Этот однострочник достигнет этого

perl -pe "$dat = $1 if /^\@(.+)/; s/^\+/+$dat/;" infile
0 голосов
/ 20 января 2012

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

sed '/^@/h;/^+/{G;s/\n@//}' file
@F7##########0/1
C4CTA6GCAAC56G67CTCA99C
+F7##########0/1
b[[WZ56W]87X9HBB
@44FC6%%%%&&&&&&&1UP1
GTS4HY2IOMD3FCCA8DFLLLTG
+44FC6%%%%&&&&&&&1UP1
]]^4YY23ZV\6`a8`^9^a
0 голосов
/ 20 января 2012

Программа, показанная ниже, делает то, что вам нужно

use strict;
use warnings;

my $str = <<'STR';
@F7##########0/1
C4CTA6GCAAC56G67CTCA99C
+
b[[WZ56W]87X9HBB
@44FC6%%%%&&&&&&&1UP1
GTS4HY2IOMD3FCCA8DFLLLTG
+
]]^4YY23ZV\6`a8`^9^a
STR

$str =~ s/^@(.+?)$(.+?)^\+/\@$1$2+$1/gms;

print $str;

OUTPUT

@F7##########0/1
C4CTA6GCAAC56G67CTCA99C
+F7##########0/1
b[[WZ56W]87X9HBB
@44FC6%%%%&&&&&&&1UP1
GTS4HY2IOMD3FCCA8DFLLLTG
+44FC6%%%%&&&&&&&1UP1
]]^4YY23ZV\6`a8`^9^a
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...