Wie kann ich an jedes vordefinierte Wort einer Textdatei eine inkrementelle Zählung anhängen?

Wie kann ich an jedes vordefinierte Wort einer Textdatei eine inkrementelle Zählung anhängen?

Wie kann ich an jedes vordefinierte Wort einer Textdatei eine inkrementelle Zählung anhängen?

Genau wie diese Frage: Wie kann ich jeder Zeile einer Textdatei eine inkrementelle Zählung anhängen?

Ich möchte einer Textdatei eine inkrementelle Zählung hinzufügen. Aber anstatt jeder Zeile eine inkrementelle Zählung hinzuzufügen, möchte ich einem vordefinierten Wort eine inkrementelle Zählung hinzufügen.

Wenn ich beispielsweise das Wort „Kino“ im Text zählen möchte, möchte ich, dass alle Vorkommen von „Kino“ in „KinoN“ geändert werden, wobei N die inkrementelle Zahl ist und der Maximalwert von N davon abhängt, wie oft das Wort „Kino“ im Text vorkommt.

So erhalten Sie eine Eingabetextdatei mit diesem Text:

Er fuhr mit dem Auto zum Kino. Anschließend ging er ins Kino, um Karten zu kaufen, und stellte anschließend fest, dass sein letzter Kinobesuch über zwei Jahre her war.

Erzeugt eine Ausgabedatei mit diesem Inhalt:

Er fuhr mit dem Auto zum Kino1. Anschließend ging er ins Kino2, um Karten zu kaufen, und stellte anschließend fest, dass sein letzter Kinobesuch mehr als zwei Jahre her war3.

Am liebsten hätte ich auch die Möglichkeit, das ausgewählte Wort rückwärts zu nummerieren.

Dies würde beispielsweise eine zweite Ausgabedatei mit folgendem Inhalt erzeugen:

Er fuhr mit dem Auto zum Kino3. Anschließend ging er ins Kino2, um Karten zu kaufen, und stellte anschließend fest, dass sein letzter Kinobesuch mehr als zwei Jahre her war1.

Antwort1

Ich würde perlhierfür Folgendes bevorzugen:

$ 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\bWort, nach dem gesucht werden soll, wobei Wortgrenzen verwendet werden, damit es nicht als Teil eines anderen Wortes übereinstimmt. Beispielsweise \bpar\bstimmt nicht überein mit apartoder parkoderspar
  • geDas gFlag dient zum globalen Ersetzen. eErmöglicht die Verwendung von Perl-Code im Ersetzungsabschnitt.
  • $&.++$iist die Verkettung des übereinstimmenden Wortes und des vorinkrementierten Wertes, $ider den Standardwert hat von0


Für den Rückwärtsgang müssen wir zuerst die Anzahl ermitteln ...

$ 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.
  • cwird zur Umgebungsvariable, die über den Hash zugänglich ist%ENV

oder, mit perlallein durch schlürfen ganze Datei

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

Antwort2

Mit GNU awk für RS mit mehreren Zeichen, Groß-/Kleinschreibung ignorierendes Matching und Wortgrenzen:

$ 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.

Antwort3

Berücksichtigen Sie die Zeichensetzung nach dem Wort.
Vorwärtsnummerierung:

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

Rückwärtsnummerierung:

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

Antwort4

Um das Wort in absteigender Reihenfolge zu markieren, invertieren wir den regulären Ausdruck UND invertieren die Daten und invertieren schließlich das Datum noch einmal, um die Transformation durchzuführen:

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

Ergebnis

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.

Um das Wort in aufsteigender Reihenfolge zu taggen, führen wir eine Lookbehind-Suche nach dem Wort durch:

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

Ergebnis

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.

verwandte Informationen