Как можно добавить инкрементный счетчик к каждому предопределенному слову текстового файла?

Как можно добавить инкрементный счетчик к каждому предопределенному слову текстового файла?

Как можно добавить инкрементный счетчик к каждому предопределенному слову текстового файла?

Как и этот вопрос: Как добавить инкрементный счетчик к каждой строке текстового файла?

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

Например, если я хочу подсчитать количество слов «кино» в тексте, я бы хотел, чтобы все упоминания слова «кино» были заменены на «киноN», где N — это порядковый номер, а максимальное значение N зависит от того, сколько раз слово «кино» встречается в тексте.

Итак, входной текстовый файл, содержащий этот текст:

Он подъехал на своей машине к кинотеатру. Затем он зашел в кинотеатр, чтобы купить билеты, и обнаружил, что прошло уже больше двух лет с тех пор, как он последний раз был там.

Создает выходной файл со следующим содержимым:

Он поехал на своей машине в кинотеатр1. Затем он зашел в кинотеатр2, чтобы купить билеты, и впоследствии обнаружил, что прошло уже более двух лет с тех пор, как он последний раз был в кинотеатре3.

Желательно также иметь возможность нумеровать выбранные слова в обратном порядке.

Т.е. это сгенерирует второй выходной файл с таким содержимым:

Он поехал на своей машине в кинотеатр3. Затем он зашел в кинотеатр2, чтобы купить билеты, и обнаружил, что прошло уже больше двух лет с тех пор, как он последний раз был в кинотеатре1.

решение1

Я бы предпочел perlдля этого:

$ cat ip.txt 
He drove his car to the cinema. He then went inside the cinema to purchase tickets, and afterwards discovered that it was more then two years since he last visited the cinema.

$ # forward counting is easy
$ perl -pe 's/\bcinema\b/$&.++$i/ge' ip.txt 
He drove his car to the cinema1. He then went inside the cinema2 to purchase tickets, and afterwards discovered that it was more then two years since he last visited the cinema3.
  • \bcinema\bслово для поиска, используя границы слов, чтобы оно не совпадало как частичная часть другого слова. Например, \bpar\bне будет соответствовать apartили parkилиspar
  • geфлаг gпредназначен для глобальной замены. eпозволяет использовать код Perl в разделе замены
  • $&.++$iпредставляет собой конкатенацию совпавшего слова и предварительно увеличенного значения, $iкоторое имеет значение по умолчанию0


Для обратного нам сначала нужно получить количество...

$ c=$(grep -ow 'cinema' ip.txt | wc -l) perl -pe 's/\bcinema\b/$&.$ENV{c}--/ge' ip.txt 
He drove his car to the cinema3. He then went inside the cinema2 to purchase tickets, and afterwards discovered that it was more then two years since he last visited the cinema1.
  • cстановится переменной окружения, доступной через хэш%ENV

или, в perlодиночку, прихлебывая весь файл

perl -0777 -pe '$c=()=/\bcinema\b/g; s//$&.$c--/ge' ip.txt 

решение2

С GNU awk для многосимвольного RS, совпадения без учета регистра и границ слов:

$ awk -v RS='^$' -v ORS= -v word='cinema' '
    BEGIN { IGNORECASE=1 }
    { cnt=gsub("\\<"word"\\>","&"); while (sub("\\<"word"\\>","&"cnt--)); print }
' file
He drove his car to the cinema3. He then went inside the cinema2 to purchase tickets, and afterwards discovered that it was more then two years since he last visited the cinema1.

решение3

С учетом знаков препинания после слова.
Прямая нумерация:

word="cinema"
awk -v word="$word" '
    { 
      for (i = 1; i <= NF; i++) 
        if ($i ~ word "([,.;:)]|$)") { 
          gsub(word, word "" ++count,$i) 
        }
      print 
    }' input-file

Обратная нумерация:

word="cinema"
count="$(awk -v word="$word" '
    { count += gsub(word, "") }
    END { print count }' input-file)"
awk -v word="$word" -v count="$count" '
    { 
      for (i = 1; i <= NF; i++) 
        if ($i ~ word "([,.;:)]|$)") { 
          gsub(word, word "" count--, $i) 
        }
      print 
    }' input-file

решение4

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

perl -l -0777pe '$_ = reverse reverse =~ s/(?=\bamenic\b)/++$a/gre' input.data

Результат

He drove his car to the cinema3. He then went inside the cinema2 to purchase tickets, and
afterwards discovered that it was more then two years since he last visited the cinema1.

Для маркировки слова в порядке возрастания мы выполняем ретроспективный поиск слова:

perl -lpe 's/\bcinema\b\K/++$a/eg' input.data

Результат

He drove his car to the cinema1. He then went inside the cinema2 to purchase tickets, and
afterwards discovered that it was more then two years since he last visited the cinema3.

Связанный контент