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 perl
hierfü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\b
Wort, nach dem gesucht werden soll, wobei Wortgrenzen verwendet werden, damit es nicht als Teil eines anderen Wortes übereinstimmt. Beispielsweise\bpar\b
stimmt nicht überein mitapart
oderpark
oderspar
ge
Dasg
Flag dient zum globalen Ersetzen.e
Ermöglicht die Verwendung von Perl-Code im Ersetzungsabschnitt.$&.++$i
ist die Verkettung des übereinstimmenden Wortes und des vorinkrementierten Wertes,$i
der 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.
c
wird zur Umgebungsvariable, die über den Hash zugänglich ist%ENV
oder, mit perl
allein 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.