2016-11-07 61 views
3
propertyOne=1 
propertyTwo=a/b 
propertyThree=three 

如何將屬性文件的內容更改爲以下模式?Bash腳本:更新屬性文件

  • propertyOne將原始值
  • propertyTwo前添加一個字符串將在中間
  • propertyThree添加一個字符串將在年底

    propertyOne=apple/1 
    propertyTwo=a/and/b 
    propertyThree=three/end 
    

我嘗試添加一個字符串使用sed -i -e但我只是成功,如果我硬編碼每行的變化;任何改善代碼的建議?

sed -i -e '/propertyTwo=/ s=.*/=one/2/two' path/to/file 
+0

屬性一將在當前變量前添加一個字符串,屬性二將在兩者之間添加一些內容,變量三將在末尾添加一些內容。它們將用斜線「/」分隔。我會更新問題的清晰度 – Led

+2

如果所有3個替換都不同,那麼您將需要3個替換,並且不能避免硬編碼屬性名稱。 – anubhava

+0

這是指出,有關如何獲得屬性值的任何想法,以減少硬編碼錯誤? – Led

回答

3

在這種情況下,一個純擊溶液同時提供靈活性和健壯性(但請參閱下面的更快速awk解決方案)。

雖然逐行讀取文件的Bash解決方案通常很慢,但這可能不會成爲屬性文件的問題,而這些文件往往很小。

#!/usr/bin/env bash 

while IFS='=' read -r prop val; do 
    case $prop in 
    propertyOne) 
     val="apple/$val" 
     ;; 
    propertyTwo) 
     val="${val/\///and/}" 
     ;; 
    propertyThree) 
     val="$val/end" 
     ;; 
    esac 
    printf '%s\n' "$prop=$val" 
done <file> file.tmp && mv file.tmp file 

的擊內置read方便提供其餘的最線邏輯: 通過僅在IFS='-' read -r prop value指定變量,所述第二可變value接收第一=一切,不管是什麼,即使它包含額外的=實例。

<file> file.tmp && mv file.tmp file是一個常見的習慣用法(寬泛地說)就地更新文件。從技術上講,修改的內容被寫入臨時文件。文件和那個溫度。文件然後替換原件。

注:
*需要更新的這種間接的方式,因爲shell不支持讀取和輸出在同一個命令相同的文件。
*這個簡單的方法是有問題的,因爲如果輸入文件是一個符號,它會被替換常規文件,新文件的權限可能會有所不同,...


awk,如karakfa's answer證明,肯定是更快的選擇,但它帶有一個警告 - 這可能是也可能不是你一個問題:

概念,屬性文件不是嚴格爲基礎的,是導致屬性值可能包含值內部=實例。

如果通過=拆分輸入字段,然後一般價值的處理是有問題的,因爲你不會有一個變量參考值整體

一個簡單的例子:假設你有一個輸入線foo=bar=baz,並要追加字符串@到現有值,bar=baz,而無需提前瞭解現有的值是否恰好有嵌入式=字符。
如果您盲目使用$2 = $2 "@"進行追加,則結果值將僅爲[email protected] - 換句話說:您已有丟失數據

解決這個問題需要多一點工作;這裏是一個awk解決方案改編自karakfa的,這在單變量val提供整個值:

awk -F= ' 
    # Capture the entire value (everything to the right of "=") in variable "val". 
    { val= $0; sub("^[^=]+=", "", val) } 
    $1 == "propertyOne" { val = "apple/" val } 
    $1 == "propertyTwo" { sub(/\//, "/and/", val) } 
    $1 == "propertyThree" { val = val "/end" } 
    { print $1 "=" val } 
' file > file.tmp && mv file.tmp file 

注:如果您使用GNUawk和版本號爲> = 4.1,則可以使用-i inplace代替的> file.tmp && mv file.tmp file更新輸入文件就地(鬆散地說)。除了比後一種方法更方便之外,-i inplace還保留了原始文件的權限,但基本方法是相同的:文件被替換爲,這會帶來用常規文件替換符號鏈接的風險。


sed是不是一個好的選擇,因爲它很難替代限制了一般地線的一部分。

+0

謝謝!但最新行的目的> file.tmp && mv file.tmp – Led

+0

Led:請參閱我的更新。我還添加了一個示例,以更好地說明爲什麼接受的答案作爲通用解決方案存在問題。 – mklement0

4

awk來救援!

$ awk -F'[=/]' '/propertyOne/{$2="apple/"$2} 
       /propertyTwo/{$2=$2"/and/"$3} 
       /propertyThree/{$2=$2"/end"} 
          {print $1 "=" $2}' file 

propertyOne=apple/1 
propertyTwo=a/and/b 
propertyThree=three/end 

定義兩個字段分隔符來引用組件。根據您的規則設置新的第二個字段並進行打印。

注意顯然,這種方法是不會,如果你有/=作爲內容的一部分工作。您可以將第一個和最後一個規則推廣到前置或附加到等式的值部分,但是第二種情況沒有辦法解決。

此外,爲了更好地控制規則,您可能需要對每種情況更改/../$1=="..."

這是另一種選擇,

$ awk -F= -v OFS='=' '$1=="propertyOne"{$2="apple/"$2} 
         $1=="propertyTwo"{sub(/\//,"/and/")} 
        $1=="propertyThree"{$NF=$NF"/end"}1' file 

測試與邊緣例

$ awk -F= ... << EOF 
> propertyOne=a==b 
> propertyTwo=a==b/c==d 
> propertyThree=x/y==z 
> Not_propertyOne=no change 
> EOF 

產量

propertyOne=apple/a==b 
propertyTwo=a==b/and/c==d 
propertyThree=x/y==z/end 
Not_propertyOne=no change