2014-09-04 38 views
1

我有一個變量的文本字符串在bash,看起來像這樣:代變量

filename1.txt 
filename2.txt 

varname1 = v1value 
$(varname1)/filename3.txt 
$(varname1)/filename4.txt 

varname2 = $(varname1)/v2value 
$(varname2)/filename5.txt 
$(varname2)/filename6.txt 

我想替換全部到位的變量,產生這樣的:

filename1.txt 
filename2.txt 

v1value/filename3.txt 
v1value/filename4.txt 

v1value/v2value/filename5.txt 
v1value/v2value/filename6.txt 

任何人都可以提出一個乾淨的方法來做到這一點在殼?

+0

這個文件有多大?這是一種問題,實際上通過一個好的文本編輯器可以更快地解決問題,除非文件非常大 – slezica 2014-09-04 20:53:00

+0

這只是一個示例。實際上有幾百個像這樣的文件,每個文件中都有0到20個替換。 – user2664470 2014-09-04 21:27:23

回答

1

我發現使用m4一個合理的解決辦法:

function make_substitutions() { 
    # first all $(varname)s are replaced with ____varname____ 
    # then each assignment statement is replaced with an m4 define macro 
    # finally this text is then passed through m4 

    echo "$1" |\ 
    sed 's/\$(\([[:alnum:]][[:alnum:]]*\))/____\1____/' | \ 
    sed 's/ *\([[:alnum:]][[:alnum:]]*\) *= *\(..*\)/define(____\1____, \2)/' | \ 
    m4 
} 
+0

您可以對任何語言或模板/宏系統使用相同類型的模式,以允許進行此類運行時評估。你甚至可以用殼體本身做一些努力(和消毒)。一個awk解決方案應該也相當簡單。 – 2014-09-04 21:35:22

0

也許

echo "$string" | perl -nlE 'm/(\w+)\s*=\s*(.*)(?{$h{$1}=$2})/&&next;while(m/\$\((\w+)\)/){$x=$1;s/\$\($x\)/$h{$x}/e};say$_' 

打印

filename1.txt 
filename2.txt 

v1value/filename3.txt 
v1value/filename4.txt 

v1value/v2value/filename5.txt 
v1value/v2value/filename6.txt 
2

在awk中:

BEGIN { 
    FS = "[[:space:]]*=[[:space:]]*" 
} 

NF > 1 { 
    map[$1] = $2 
    next; 
} 

function replace( count) 
{ 
    for (key in map) { 
     count += gsub("\\$\\("key"\\)", map[key]) 
    } 

    return count 
} 

{ 
    while (replace() > 0) {} 
    print 
} 

在lua中:

local map = {} 

--for line in io.lines("file.in") do -- To read from a file. 
for line in io.stdin:lines() do -- To read from standard input. 
    local key, value = line:match("^(%w*)%s*=%s*(.*)$") 
    if key then 
     map[key] = value 
    else 
     local count 
     while count ~= 0 do 
      line, count = line:gsub("%$%(([^)]*)%)", map) 
     end 
     print(line) 
    end 
end