已更新
假设我有一个包含此内容的文件
database_driver="pdo_mysql"
database_host="11.22.33.44"
database_port="3306"
%database_driver%
%database_host%
%database_port%
现在我想用相应变量的内容替换%database *****%,所以我最终会用
pdo_mysql
11.22.33.44
3306
我现在如何逐行完成此操作,但我希望有一个sed replace命令一次替换所有值
我试过这个
sed -r "s/%(database.*)%/$\1/g" file.yml
我正在尝试从第二个反向引用创建变量,但这不起作用,它得到了这个
$database_driver
所以我得到变量的名称,而不是值
有什么想法吗?
更新 我有很多答案但是它们似乎都没有用,而且看起来都非常困难。 我仍然想回答我最初的问题:有没有办法让这项工作
sed -r "s/%(database.*)%/$\1/g" file.yml
这取代了
%SOMETHING% into $SOMETHING
和
%SOMETHING_ELSE% into $SOMETHING_ELSE.
但我需要$ SOMETHING和$ SOMETHING_ELSE的值 这是我猜的最理想的解决方案。所提出的解决方案更短,更易读
答案 0 :(得分:1)
我会使用awk
,如下所示:
awk -F'"| +' '$1=="database_driver="{d=$2}/%database_driver%/{$2=d}1' a.txt
在GNU grep
的帮助下,你甚至可以使用它:
driver=$(grep -oP 'driver="\K[^"]+' a.txt)
sed "s/%database_driver%/$driver/" a.txt
答案 1 :(得分:1)
全部在sed lol
sed '/^database.*=/{p;s/\(database[^=]*\)/%\1%/;H;d};/^%database/{G;s/^\([^\n]*\).*\1="\([^"]*\).*/\2/}' file
基本上它会保存您想要的值,然后将要替换的行替换为它保存的值。
将在以后匹配时使用通用数据。
database_driver="pdo_mysql"
database_host="11.22.33.44"
database_port="3306"
pdo_mysql
11.22.33.44
3306
正如hek2mgl所提到的,你也可以把它放在一个脚本文件中
/^database.*=/{p;s/\(database[^=]*\)/%\1%/;H;d}
/^%database/{G;s/^\([^\n]*\).*\1="\([^"]*\).*/\2/}
以
运行sed -f "sedscript" file
答案 2 :(得分:1)
$ sed -f <(sed '/^$/ q; s/\([^=]*\)="\([^"]*\)"/s|%\1%|\2|;/' file) file
database_driver="pdo_mysql"
database_host="11.22.33.44"
database_port="3306"
%database_driver%
%database_host%
%database_port%
database_driver="pdo_mysql"
database_host="11.22.33.44"
database_port="3306"
pdo_mysql
11.22.33.44
3306
sed '/^$/ q; s/\([^=]*\)="\([^"]*\)"/s|%\1%|\2|;/'
为外部sed
创建命令输入。它在空行停止,在此之前,将赋值表达式转换为表达式,例如:
s|%database_driver%|pdo_mysql|;
s|%database_host%|11.22.33.44|;
s|%database_port%|3306|;
这使得"
在bash中表现得像'
一样(没有转义序列或使用这些双引号进行插值),并假设%之间没有任何内容对sed
特殊的字符(您可以通过将[^=]
替换为一系列允许的字符(例如[_0-9a-zA-Z]
)来确保这一点。
注意:您可能希望在适当的模板语言中编写模板,例如ERB或Handlerbars,而不是这样做。
答案 3 :(得分:1)
我使用Perl。这在Perl中比在sed中容易得多。例如:
perl -pe 's/%([^%]*)%/$vars{$1}/eg; if (/(\w+)="(.*)"/) { $vars{$1} = $2; }' filename
更可读:
s/%(\w+)%/$vars{$1}/eg; # replace %%-encased words with the remembered value
# for the encased word
if (/(\w+)="(.*)"/) { # When finding an assignment
$vars{$1} = $2; # remember the assigned value.
}
这种方法甚至可以让你在变量赋值中使用变量,也就是说输入
database_driver="pdo_mysql"
database_host="11.22.33.44"
database_port="3306"
database_connstr="mysql:host=%database_host%;port=%database_port%"
%database_driver%
%database_host%
%database_port%
%database_connstr%
产生
database_driver="pdo_mysql"
database_host="11.22.33.44"
database_port="3306"
database_connstr="mysql:host=11.22.33.44;port=3306"
pdo_mysql
11.22.33.44
3306
mysql:host=11.22.33.44;port=3306
答案 4 :(得分:1)
这个sed
命令将执行:
sed -nr 's#database_([^"]*)="([^"]*)"#s/(\1:\\s*)%[^%]*%/\\1\2/#p' file| sed -r -f- file
sed -nr 's#database_([^"]*)="([^"]*)"#s/(\1:\\s*)%[^%]*%/\\1\2/#p' file
生成输出:
s/(driver:\s*)%[^%]*%/\1pdo_mysql/
s/(host:\s*)%[^%]*%/\111.22.33.44/
s/(port:\s*)%[^%]*%/\13306/
然后用作管道后下一个sed
的{{1}}脚本。
对于您的新文件,它将是:
sed
答案 5 :(得分:0)
Sed用于单个行上的简单替换,这就是全部。只需使用awk:
$ awk -F'[="%]' 'NF==4{map[$1]=$3;next} NF{print map[$2]}' file
pdo_mysql
11.22.33.44
3306