2

У меня есть файл с несколькими абзацами, разделенными пустой строкой. Технически это не параграфы, а просто разделы текста, разделенные пустой строкой.

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

This is text.
This is more text.
Even more text!

This is text in section two.
Some more text.
You get the point...

Я хочу заставить это сказать:

1This is text
this is more text
Even more text!

2This is text in section two.
Some more text.
You get the point...

2 ответа2

1

В общем, использование оболочки для разбора текста очень медленное и громоздкое. Вот еще несколько вариантов:

  1. Perl в "режиме абзаца"

    perl -00pe 's/^/$./' file 
    

    объяснение

    -00 включает режим абзаца, где "строки" определяются последовательными \n\n , другими словами. s/^/$./ заменит начало строки (^) на текущий номер строки (параграфа) $. , -p указывает perl печатать каждую строку входного файла после запуска скрипта, заданного для него -e .

  2. Awk

    awk -vRS='\n\n' -vORS='\n\n' '{print NR$0}' file
    

    объяснение

    -vRS='\n\n' устанавливает разделитель записей awk для последовательных символов новой строки. Подобно режиму абзацев в perl, он делает абзацы "линиями". Затем мы говорим ему напечатать текущий номер строки (NR) и текущую "строку" $0 . Параметр -vORS= устанавливает разделитель выходной записи на последовательные символы новой строки, чтобы абзацы также отделялись пустыми строками в выходных данных. Обратите внимание, что это добавит 2 пустые строки в конце вывода. Чтобы избежать этого, вы можете использовать head:

    awk -v RS='\n\n' -vORS='\n\n' '{print NR$0}' file | head -n -2
    

Для сравнения, вот времена, когда различные решения принимались в моей системе при запуске с тестовым файлом 10M:

$ time a.sh > /dev/null ## a.sh is Cyrus's solution

real    0m1.419s
user    0m1.308s
sys     0m0.104s

$ time perl -00pe 's/^/$./' file  > /dev/null 

real    0m0.087s
user    0m0.084s
sys     0m0.000s

$ time awk -v RS='\n\n' -vORS='\n\n' '{print NR$0}' file | head -n -2 >/dev/null

real    0m0.074s
user    0m0.056s
sys     0m0.020s

Как вы можете видеть выше, как perl, так и awk-решения на порядок быстрее, чем подход оболочки.

1

Попробуйте это с помощью встроенных команд bash:

#!/bin/bash

l=1                          # paragraph counter
echo -n $l                   # print paragraph counter without new line
while read x; do             # read current line from file, see last line
  if [[ $x == "" ]]; then    # empty line?
    echo                     # print empty line
    read x                   # read next line from file, see last line
    ((l++))                  # increment paragraph counter
    echo -n $l               # print paragraph counter without new line
  fi
  echo "$x"                  # print current line
done < file

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .