2017-02-28 34 views
2

我有一個包含更換和增加信件和其他具有AWK號碼或sed的

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

一個這個腳本的目標是基於價值發現以前遞增nginx的緩存兩位數字的字符串文件。爲了做到這一點,我用這個代碼:

# 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 

也許不那麼優雅,但它的工作原理。

另一個目標是增加MYSITE XMYSITEP的所有出現的最後一個字母,在這種情況下,應該成爲MYSITE Q,MYSITE後P,等等等等,一旦MYSITE ž將達到添加另一封信中,像MYSITE AA,MYSITE AB,等等,等等

我想是這樣的:

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

但它不能工作原因MYSITEGG是一個靜態值,不能使用。 如何計算最後一個字母,將它增加到下一個字母,一旦最後一個Z字母到達,再添加一個字母?

謝謝!

+3

Perl增加字母。我建議你想要'perl -p -e'解決方案。如果你願意,可以添加標籤。 – stevesliva

回答

4

Perl的自動增量將工作的字母和數字,以完全相同的方式,你描述

我們可以和整潔你的nginx-cache增量,以及我們在它

我認爲SITENAME保存文件的名稱進行修改?

它看起來像這樣。我要捕捉$1分配給一個普通變量$n遞增它,因爲$1是隻讀的

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

如果你願意的話,這可以在一個單一的替換完成,這樣

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

哇!這是一個非常好的解決方案!一切都在一條線上!它像一個魅力。非常感謝@Borodin! – fabreg

2

注意:下面的溶液是不必要的複雜,因爲作爲Borodin's helpful answer演示(以及@ stevesliva的評論關於這個問題的暗示),的Perl 直接支持遞增的字母的字母順序在問題中描述的方式,通過將++運算符應用於包含字母(序列)的變量;例如:

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

下面可能仍然是感興趣作爲如何Perl的功率可以從外殼被利用帶註釋的展示,示出的技術,如將溶液:

  • 使用s///e以確定用表達式替換字符串。
  • 將字符串分割爲一個字符陣列(split //, "...."
  • 使用的ordchr函數來獲得一個字符的碼點,並轉換一個(N遞增)編碼點返回一個字符。
  • 字符串複製(x運營商)
  • 數組索引和切片:
    • 得到一個數組的最後一個元素($chars[-1]
    • 讓所有,但一個數組(@chars[0..$#chars-1]
  • 的最後一個元素

A perl溶液(實際上是一個重新實現的東西++可以直接做):

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 

產量:

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

您可以使用perl-i選項,結果
更換輸入文件 (perl -i -pe '...' "$SITENAME")。

作爲鮑羅廷的回答表明,它並不難解決所有任務單獨使用perl的問題。

s函數的/e選項允許使用一個Perl 表達的用於確定所述替換字符串,使複雜的替換:

  • $1引用當前MYSITE後綴中的表達。

  • @chars = split qr(), $1將後綴拆分爲字符數組。

  • $chars[-1] eq "Z"測試是否最後加後綴char。是Z

    • 如果是這樣:後綴被替換所有A S,與所附
      "A" x (1 + scalar @chars))的附加A

    • 否則:最後一個後綴char。在字母表
      join "", @chars[0..$#chars-1], chr (1 + ord $chars[-1]))被替換爲下面這封信

+1

代替'grep |的長時間運行sed | awk |沒有學習一種新語言,可能更容易找到帶有單個Awk腳本的sed'。一般來說,如果你使用的是Awk,你應該只需要非常少而且非常節省地在同一個管道中需要'grep'或'sed'。但在這種特殊情況下,Perl似乎很適合,因爲它支持OP描述的行爲。 – tripleee

+1

您也可以使用帶字母或零填充整數的'..'運算符。 (''A'..'Z'')操作符中隱藏了許多字符串操作功能,您可能不會期望它。 – stevesliva

+1

謝謝大家的出色解決方案!我試了@鮑羅廷的一個,它完美的工作! – fabreg