2016-11-07 106 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