Как я могу редактировать диапазон текста между 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]