2017-02-28 21 views
2

ich eine Zeichenfolge, dieersetzen und Schritt Buchstaben und Zahlen mit awk oder sed

fastcgi_cache_path /var/run/nginx-cache15 levels=1:2 keys_zone=MYSITEP:100m inactive=60m; 

Eines der Ziele dieses Skript enthält, ist nginx-Cache zwei Stellen zu erhöhen, basierend auf dem Wert finden bei früheren Datei. Dafür benutze ich diesen Code:

# Replace cache_path 

PREV=$(ls -t /etc/nginx/sites-available | head -n1) #find the previous cache_path number 
CACHE=$(grep fastcgi_cache_path $PREV | awk '{print $2}' |cut -d/ -f4) #take the string to change 
SUB=$(echo $CACHE |sed "s/nginx-cache[0-9]*[0-9]/&@/g;:a {s/[email protected]/1/g;s/[email protected]/2/g;s/[email protected]/3/g;s/[email protected]/4/g;s/[email protected]/5/g;s/[email protected]/6/g;s/[email protected]/7/g;s/[email protected]/8/g;s/[email protected]/9/g;s/[email protected]/@0/g;t a};s/@/1/g") #increment number 
sed -i "s/nginx-cache[0-9]*/$SUB/g" $SITENAME #replace number 

Vielleicht nicht so elegant, aber es funktioniert.

Das andere Ziel ist letzte Buchstaben aller Vorkommen von MySite x (MYSITEP, in diesem Fall zu erhöhen, soll MySite werden Q nach MySite P usw. usw. und einmal MySite Z wird erreicht wieder einen Brief schreiben, mySite AA, mySite AB, etc. etc.

ich dachte, so etwas wie:

sed -i "s/MYSITEP[A-Z]*/MYSITEGG/g" $SITENAME 

aber es kann nicht funktionieren Ursache MYSITEGG ist ein statischer Wert und kann nicht verwendet werden. Wie kann ich den letzten Buchstaben berechnen, ihn auf den nächsten erhöhen und sobald der letzte Z-Buchstabe erreicht ist, einen weiteren Buchstaben hinzufügen?

Vielen Dank!

+3

Perl inkrementiert Buchstaben. Ich schlage vor, Sie werden 'perl -p -e'-Lösungen wollen. Fügen Sie das Tag hinzu, wenn Sie dafür offen sind. – stevesliva

Antwort

4

Perl wird mit dem folgenden Buchstaben im Alphabet ersetzt autoincrement wird sowie Ziffern auf Buchstaben arbeiten, in genau der Art und Weise Sie beschreiben

Wir können auch ordentlich als auch Ihr nginx-cache Zuwachs, während wir gerade dabei sind

ich gehe davon aus SITENAME den Namen der Datei geändert wird, hält?

Es würde so aussehen.Ich muß die Erfassung $1 zu einem gewöhnlichen Variable $n zuweisen es zu erhöhen, als $1 nur gelesen wird

perl -i -pe 's/nginx-cache\K(\d+)/ ++($n = $1) /e; s/MYSITE\K(\w+)/ ++($n = $1) /e;' $SITENAME 

Wenn Sie möchten, kann dies in einer einzigen Substitution durchgeführt werden, wie dies

perl -i -pe 's/(?:nginx-cache|MYSITE)\K(\w+)/ ++($n = $1) /ge' $SITENAME 
+0

Wow! Das ist eine wirklich schöne Lösung! Alles in einer Linie! Es wirkt wie ein Zauber. Vielen Dank @Borodin !! – fabreg

2

Hinweis: Die Lösung unten ist unnötig kompliziert, denn wie Borodin's helpful answer zeigt (und Kommentar des @ stevesliva auf die Frage angedeutet), Perl direkt unterstützt Buchstaben alphabetisch in der Weise, in der Frage beschrieben erhöht wird, durch Anwenden des ++-Operators auf eine Variable, die einen Buchstaben (Sequenz) enthält; Beispiel:

$ perl -E '$letters = "ZZ"; say ++$letters' 
AAA 

Die Lösung unterhalb konnte noch von Interesse sein als ein kommentierter Schaufenster, wie Perl Leistung kann aus der Schale nutzbar gemacht werden, was zeigt, Techniken wie:

  • Verwendung von s///e um zu bestimmen, die Ersetzungszeichenfolge mit einem Ausdruck.
  • Splitting eine Zeichenfolge in ein Zeichenfeld (split //, "....")
  • Verwendung der ord und chr Funktionen der Codepunkt eines char zu bekommen., Und Konvertieren in ein char a (n inkrementiert) Codepoint zurück.
  • String-Replikation (x Operator)
  • Array-Indizierung und Scheiben:
    • eines Arrays letzte Element ($chars[-1])
    • bekommen alle, aber das letzte Element eines Arrays (@chars[0..$#chars-1])
  • bekommen

A perl Lösung (in der Tat eine Neuimplementierung von dem, was ++ direkt tun können):

perl -pe 's/\bMYSITE\K([A-Z]+)/ 
    @chars = split qr(), $1; $chars[-1] eq "Z" ? 
    "A" x (1 + scalar @chars) 
    : 
    join "", @chars[0..$#chars-1], chr (1 + ord $chars[-1]) 
/e' <<'EOF' 
...=MYSITEP:... 
...=MYSITEZP:... 
...=MYSITEZZ:... 
EOF 

ergibt:

...=MYSITEQ:... # P -> Q 
...=MYSITEZQ:... # ZP -> ZQ 
...=MYSITEAAA:... # ZZ -> AAA 

Sie können perl verwenden ‚s -i Option, um die Eingabedatei mit dem Ergebnis zu ersetzen
(perl -i -pe '...' "$SITENAME").

Als Borodins Antwort zeigt, ist es nicht schwer alle Aufgaben in der Frage perl mit allein zu lösen.

Die /e der s Funktion Option ermöglicht die Verwendung eines Ausdrucks Perl für die Ersatzzeichenfolge zu bestimmen, der anspruchsvollen Ersatz ermöglicht:

  • $1 verweist auf den aktuellen MYSITE Suffix im Ausdruck.

  • @chars = split qr(), $1 teilt das Suffix in ein Zeichenfeld auf.

  • $chars[-1] eq "Z" testet, ob das letzte Suffix char. Z ist

    • Wenn ja: Das Suffix ist mit allen A s ersetzt, mit einer zusätzlichen A
      beigefügten ("A" x (1 + scalar @chars)).

    • Sonst: Das letzte Suffix char.
      (join "", @chars[0..$#chars-1], chr (1 + ord $chars[-1]))

+1

Ersetzen langer Läufe von 'grep | sed | awk | sed' mit einem einzigen Awk-Skript könnte leichter erreichbar sein, ohne eine neue Sprache zu lernen. Im Allgemeinen, wenn Sie Awk verwenden, sollten Sie 'grep' oder' sed' in der gleichen Pipeline nur sehr selten und sehr sparsam verwenden. Aber in diesem speziellen Fall scheint Perl eine gute Lösung zu sein, da es das Verhalten des OP direkt nach dem Auspacken unterstützt. – tripleee

+1

Sie können auch den Operator '..' mit Buchstaben oder Null-gefüllten Ganzzahlen verwenden. (''A' .. 'Z'') Es gibt eine Menge Funktionen zur Manipulation von Strings, die in Operatoren verborgen sind, wo Sie es nicht erwarten würden. – stevesliva

+1

Danke euch allen für die geniale Lösung! Ich habe das @ Borodin's probiert und es funktioniert einwandfrei! – fabreg