2011-08-05 52 views
7

文件,我需要修改包含以下內容:可能涉及到算術的Sed替換?

block: 16, size: 16, start: 8, length: 4 

我想要的文件,以便爲大小將2 開始分,而值,長度值將被乘以2.

因爲我必須對一大堆文件進行這樣的修改,所以我正在考慮使用Sed爲我做替換工作。但我不確定在匹配和替代過程中是否允許計算。

回答

8

我總是試着用sed來解決標記爲的每個問題。但在這裏,要完成awk所要做的事情,這很容易。 (在這種情況下使用的sed是太困難了。)所以,這裏使用awk我的解決方案:

$ echo "block: 16, size: 16, start: 8, length: 4" | awk '{ 
    printf "%s %d, %s %d, %s %d, %s %d\n", $1, $2/2, $3, $4/2, $5, $6*2, $7, $8*2 
}' 
block: 8, size: 8, start: 16, length: 8 
+1

當條目的順序不同時,這不起作用,例如, G。 '「block:16,start:8,size:8,length:4」' –

0

不要以爲這是可能的。見例如http://www.delorie.com/gnu/docs/sed/sed_15.html

但是,如果您只有一小塊可能的值,塊,大小,開始和長度,它可能是最快硬編碼所需的替換。下一個最簡單的選項可能是使用awk,但不能就地修改文件。

5

Perl是有用的位置:

perl -pe ' 
    s{(\D+)(\d+)(\D+)(\d+)(\D+)(\d+)(\D+)(\d+)} 
    {$1 . $2/2 . $3 . $4/2 . $5 . $6*2 . $7 . $8*2}e 
' file 

如果你想編輯您的文件-place,perl有像sed這樣的-i選項。

+1

你的意思是說* sed *具有'-i'選項,就像* perl *,而不是相反。您不會在* sed *,BTW的POSIX規範的所需選項列表中找到'-i'選項,而只是在特定供應商端口中偶爾和非正式地選擇。閱讀:'sed -i' **不是普遍支持**,雖然'perl -i'是。 – tchrist

5

(這樣做的正確的工具是AWK,但對於SED運動的樂趣......)

有可能在sed。畢竟,由2乘法是根據一些簡單的規則設置的最後一位數字的取代:

  • 0 - > 0
  • 1 - > 2
  • 2 - > 4
  • 3 - > 6
  • ...
  • 8 - > 16
  • 9 - > 18

爲了照顧進位數字,每個規則應該寫兩次。

這sed腳本,可以與sed -f script運行,通過對輸入線的所有數字的2做乘法:由2

s/$/\n\n/ 
:loop 
s/0\n1\n/\n\n1/;t loop 
s/0\n\n/\n\n0/;t loop 
s/1\n1\n/\n\n3/;t loop 
s/1\n\n/\n\n2/;t loop 
s/2\n1\n/\n\n5/;t loop 
s/2\n\n/\n\n4/;t loop 
s/3\n1\n/\n\n7/;t loop 
s/3\n\n/\n\n6/;t loop 
s/4\n1\n/\n\n9/;t loop 
s/4\n\n/\n\n8/;t loop 
s/5\n1\n/\n1\n1/;t loop 
s/5\n\n/\n1\n0/;t loop 
s/6\n1\n/\n1\n3/;t loop 
s/6\n\n/\n1\n2/;t loop 
s/7\n1\n/\n1\n5/;t loop 
s/7\n\n/\n1\n4/;t loop 
s/8\n1\n/\n1\n7/;t loop 
s/8\n\n/\n1\n6/;t loop 
s/9\n1\n/\n1\n9/;t loop 
s/9\n\n/\n1\n8/;t loop 
s/\n1\n/\n\n1/;t loop 
s/\(.\)\n\n/\n\n\1/;t loop 
s/^\n\n// 

分割偶數,是相同的邏輯,但是從左到右而不是從右到左:

s/^/\n\n/ 
:loop 
s/\n1\n0/5\n\n/;t loop 
s/\n\n0/0\n\n/;t loop 
s/\n1\n1/5\n1\n/;t loop 
s/\n\n1/\n1\n/;t loop 
s/\n1\n2/6\n\n/;t loop 
s/\n\n2/1\n\n/;t loop 
s/\n1\n3/6\n1\n/;t loop 
s/\n\n3/2\n1\n/;t loop 
s/\n1\n4/7\n\n/;t loop 
s/\n\n4/2\n\n/;t loop 
s/\n1\n5/7\n1\n/;t loop 
s/\n\n5/2\n1\n/;t loop 
s/\n1\n6/8\n\n/;t loop 
s/\n\n6/3\n\n/;t loop 
s/\n1\n7/8\n\n/;t loop 
s/\n\n7/3\n1\n/;t loop 
s/\n1\n8/9\n\n/;t loop 
s/\n\n8/4\n\n/;t loop 
s/\n1\n9/9\n1\n/;t loop 
s/\n\n9/4\n1\n/;t loop 
s/\n1\n/5\n\n/;t loop 
s/\n\n\(.\)/\1\n\n/;t loop 
s/\n\n$// 

結合的,這個腳本做的工作:

h 
s/, start.*// 
s/^/\n\n/ 
t loopa 
:loopa 
s/\n1\n0/5\n\n/;t loopa 
s/\n\n0/0\n\n/;t loopa 
s/\n1\n1/5\n1\n/;t loopa 
s/\n\n1/\n1\n/;t loopa 
s/\n1\n2/6\n\n/;t loopa 
s/\n\n2/1\n\n/;t loopa 
s/\n1\n3/6\n1\n/;t loopa 
s/\n\n3/2\n1\n/;t loopa 
s/\n1\n4/7\n\n/;t loopa 
s/\n\n4/2\n\n/;t loopa 
s/\n1\n5/7\n1\n/;t loopa 
s/\n\n5/2\n1\n/;t loopa 
s/\n1\n6/8\n\n/;t loopa 
s/\n\n6/3\n\n/;t loopa 
s/\n1\n7/8\n\n/;t loopa 
s/\n\n7/3\n1\n/;t loopa 
s/\n1\n8/9\n\n/;t loopa 
s/\n\n8/4\n\n/;t loopa 
s/\n1\n9/9\n1\n/;t loopa 
s/\n\n9/4\n1\n/;t loopa 
s/\n1\n/5\n\n/;t loopa 
s/\n\n\(.\)/\1\n\n/;t loopa 
s/\n\n$// 
H 
g 
s/.*, start/, start/ 
s/\n.*// 
s/$/\n\n/ 
t loopb 
:loopb 
s/0\n1\n/\n\n1/;t loopb 
s/0\n\n/\n\n0/;t loopb 
s/1\n1\n/\n\n3/;t loopb 
s/1\n\n/\n\n2/;t loopb 
s/2\n1\n/\n\n5/;t loopb 
s/2\n\n/\n\n4/;t loopb 
s/3\n1\n/\n\n7/;t loopb 
s/3\n\n/\n\n6/;t loopb 
s/4\n1\n/\n\n9/;t loopb 
s/4\n\n/\n\n8/;t loopb 
s/5\n1\n/\n1\n1/;t loopb 
s/5\n\n/\n1\n0/;t loopb 
s/6\n1\n/\n1\n3/;t loopb 
s/6\n\n/\n1\n2/;t loopb 
s/7\n1\n/\n1\n5/;t loopb 
s/7\n\n/\n1\n4/;t loopb 
s/8\n1\n/\n1\n7/;t loopb 
s/8\n\n/\n1\n6/;t loopb 
s/9\n1\n/\n1\n9/;t loopb 
s/9\n\n/\n1\n8/;t loopb 
s/\n1\n/\n\n1/;t loopb 
s/\(.\)\n\n/\n\n\1/;t loopb 
s/^\n\n// 
H 
g 
s/[^\n]*\n// 
s/\n// 

(在AWK思想要容易得多。)

注:我曾經看到一個圖靈機的實現是sed,所以我儘量要記住,任何可以使用的編程語言來完成可以在sed來完成。當然,這並不意味着sed在所有情況下都是很好的工具。

+0

我還沒有試圖理解這一點,但根據您的評論,似乎這將失敗,除了一位數字之外的任何東西。您不能僅替換隔離的最後一個數字。 –

+0

我知道我不能僅替換最後一個數字。這就是爲什麼我有2'\ n'。對於乘法,右邊是解決方案,中間是進位數字。 – jfg956