Led*_*Led 3 bash properties-file
propertyOne=1
propertyTwo=a/b
propertyThree=three
Run Code Online (Sandbox Code Playgroud)
如何将属性文件的内容更改为以下模式?
propertyThree 将在末尾添加一个字符串
propertyOne=apple/1
propertyTwo=a/and/b
propertyThree=three/end
Run Code Online (Sandbox Code Playgroud)我尝试使用,sed -i -e
但只有对每一行的更改进行硬编码才能成功;任何改进代码的建议?
sed -i -e '/propertyTwo=/ s=.*/=one/2/two' path/to/file
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
定义两个字段分隔符以便能够引用组件。根据您的规则设置新的第二个字段并打印。
注意显然,如果您有/
或=
作为内容的一部分,您可以概括第一个和最后一个规则以将其添加到方程的值部分,但无法解决第二种情况。
/../
另外为了更好地控制您可能想要更改的规则$1=="..."
。
这是另一种选择,
$ awk -F= -v OFS='=' '$1=="propertyOne"{$2="apple/"$2}
$1=="propertyTwo"{sub(/\//,"/and/")}
$1=="propertyThree"{$NF=$NF"/end"}1' file
Run Code Online (Sandbox Code Playgroud)
使用边缘情况进行测试
$ awk -F= ... << EOF
> propertyOne=a==b
> propertyTwo=a==b/c==d
> propertyThree=x/y==z
> Not_propertyOne=no change
> EOF
Run Code Online (Sandbox Code Playgroud)
产量
propertyOne=apple/a==b
propertyTwo=a==b/and/c==d
propertyThree=x/y==z/end
Not_propertyOne=no change
Run Code Online (Sandbox Code Playgroud)
在这种情况下,纯 Bash 解决方案提供了灵活性和健壮性(但请参阅下文了解更快的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
Run Code Online (Sandbox Code Playgroud)
Bash 内置函数read
方便地提供了其余的逻辑:通过只在 中指定2 个变量IFS='-' read -r prop value
,第二个变量value
接收第一个变量之后的所有内容=
,无论它是什么,即使它包含其他=
实例。
< file > file.tmp && mv file.tmp file
是(松散地说)就地更新文件的常用习惯用法。从技术上讲,修改后的内容被写入临时文件。文件,以及那个临时文件。文件然后替换原来的。
注意:
* 需要这种间接更新方式,因为shell 不支持在同一命令中读取和输出到同一文件。
* 这种简单的方法可能有问题,因为如果输入文件是符号链接,则将其替换为常规文件,新文件的权限可能不同,...
awk
,如karakfa's answer 所示,当然是更快的选择,但它有一个警告 - 这对您来说可能是也可能不是问题:
从概念上讲,属性文件并非严格基于字段,因为属性值可能包含值内部 =
实例。
如果将输入拆分为字段=
,则泛型值处理可能会出现问题,因为您将不会有单个变量将值作为一个整体引用。
一个简单的例子:假设您有一个输入 line foo=bar=baz
,并且您想将 string 附加@
到现有值,bar=baz
,而不必提前知道现有值是否恰好具有嵌入的=
字符。
如果您盲目地使用$2 = $2 "@"
append ,则结果值将只是bar@
- 换句话说:您丢失了数据。
解决这个问题需要做更多的工作;这是一个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
Run Code Online (Sandbox Code Playgroud)
注意:如果您使用GNU awk
并且版本号 >= 4.1,则可以使用-i inplace
代替> file.tmp && mv file.tmp file
就地更新输入文件(粗略地说)。除了比后一种方法更方便外,-i inplace
还保留了原始文件的权限,但基本方法是相同的:文件被替换,这承担了用常规文件替换符号链接的风险。
sed
不是一个好的选择,因为很难以通用方式将替换限制为一行的一部分。