Как я могу редактировать диапазон текста между 2 символами? awk, sed, regex
Используя символ "*" (это не обязательно должен быть любой специальный символ, чтобы указать), как я могу отредактировать текст из этого:
*berry
straw
rasp
blue
boysen
*
blahblah
blahblah
blahblah
*berry
straw
blue
*
blah
*table
vege
pingpong
*
К этому:
strawberry
raspberry
blueberry
boysenberry
blahblah
blahblah
blahblah
strawberry
blueberry
blah
vegetable
pingpongtable
Каждый символ после первой подходящей звездочки будет помещен в каждую строку, пока не будет найдено 2-е совпадение звездочек.
Есть какие-нибудь указания о том, как я могу это сделать? (sed или awk предпочтительнее, но если вы можете придумать другой способ, пожалуйста, напишите мне свой код!)
Я знаю, как удалить все строки, содержащие звездочку, это просто часть размещения символов, о которой я не могу думать
5 ответов
Это awk
кода может быть достаточно:
awk -F'*' 'NF == 2 {label = $2; next} {$0 = $0 label} 1'
Чтобы сломать это:
- использование
*
в качестве разделителя полей. Таким образом, мы можем просто проверить количество полей (NF
) определить, достигнут ли начало или конец блока. - Когда есть два поля, мы сохраняем второе поле в
label
и перейти к следующей строке. - С тех пор мы добавляем, что
label
к текущей строке, а затем распечатайте. Если метка пуста, мы находимся вне блока, и никакого эффекта нет. Если нет, мы получаем требуемый результат.
В sed
Вы можете скопировать "специальную" строку в пространство для хранения перед удалением
sed -e '/^\*/{h;d;}'
и затем добавьте пространство удержания к каждому последующему пространству шаблона, заменив получившийся символ новой строки и маркер
-e '{G;s/\n\*//;}'
Проверяя это с вашими данными,
$ sed -e '/^\*/{h;d;}' -e '{G;s/\n\*//;}' file
strawberry
raspberry
blueberry
boysenberry
blahblah
blahblah
blahblah
strawberry
blueberry
blah
vegetable
pingpongtable
Примечание: это не останавливается, когда он встречает вторую звездочку; он делает то же самое, но добавляет *
ничего не следует - пока не совпадет со следующим *sometext
,
Вот способ Perl:
$ perl -lne '/^\*(.*)/ || print "$_$1"' file
strawberry
raspberry
blueberry
boysenberry
blahblah
blahblah
blahblah
strawberry
blueberry
blah
vegetable
pingpongtable
объяснение
-n
заставит Perl прочитать каждую строку входного файла, сохранив ее в специальной переменной $_
, -l
приведет к тому, что я) лишить завершающие символы новой строки (\n
) из каждой строки и II) добавить новую строку для каждого вызова print
, -e
скрипт, который применяется к каждой строке
/^\*(.*)/
: сопоставить строки, начинающиеся со звездочки, и сохранить все после звездочки как$1
(это то, что делают скобки).|| print "$_$1"'
:||
логичноOR
, Следовательноprint
будет выполняться только в том случае, если текущая строка не начинается со звездочки. Если это так, мы печатаем текущую строку ($_
) вместе с тем, что в настоящее время сохраняется как$1
(шаблон, следующий за звездочкой).
Как обычно, есть много способов сделать это. Глупый и неэффективный, но подчеркивающий возможности командной строки для работы со строками:
$ while read line; do
[[ $line =~ ^\* ]] && pat="${line#\*}" || printf "%s%s\n" "$line" "$pat";
done < file
strawberry
raspberry
blueberry
boysenberry
blahblah
blahblah
blahblah
strawberry
blueberry
blah
vegetable
pingpongtable
объяснение
while read line; do ... ; done < file
: это классикаwhile
цикл, который будет читать каждую строку входного файлаfile
и сохранить его как$line
,[[ $line =~ ^\* ]] && pat="${line#\*}"
: если строка начинается с*
, удали все после этого (вот что${line#\*}
делает, для более подробной информации, см. здесь) и сохранить его как$pat
, *|| printf "%s%s\n" "$line" "$pat";
: если предыдущая команда завершилась неудачно (строка не начинается со звездочки), выведите строку и текущее значение$pat
,
Через мой любимый питон...
with open('/path/to/the/file') as f:
counter = False
for line in f:
if line.startswith('*') and not counter:
m = line.strip().lstrip('*')
counter = True
elif line.startswith('*') and counter:
counter = False
elif counter:
if not line.startswith('*'):
print(line.strip() + m)
else:
print(line.strip())
Пришел сюда поздно. Вот еще один python
подход:
#!/usr/bin/env python2
with open('/path/to/file.txt') as f:
for lines in f.read().split('*'):
entries = lines.rstrip().split('\n')
for i in range(1, len(entries)):
print entries[i] + entries[0]