【发布时间】:2016-03-28 19:19:47
【问题描述】:
我想用另一个替换文件中的一个字符串,更具体地说,替换 dovecot passwd 文件 (/etc/dovecot/passwd) 中的 username:password 条目,但前提是记录存在。
那么,我需要什么:
-
sed命令 - 如果记录不存在则不执行任何操作(参见 dovecot passwd 示例)
- 在文件中替换(如果没有很好的理由输出到新文件并将新文件移动到原始文件)
这里是/etc/dovecot/passd 示例:
johndoe@example.com:{CRAM-MD5}479375185777b7ba573747c111483bdd628332a70268ce283dc80bedd0f65988
janedoe@example.com:{CRAM-MD5}10b7176649d8bb3eb38f6b68a0c6c826ffab5656181821e598296ebd31e8f64f
以及到目前为止我尝试过的内容(创建新文件,输出到新文件并将 mv 输出到原始文件即使记录不存在)
#!/usr/bin/env php
<?php
$passwd_file = '/etc/dovecot/passwd';
$time = time();
$newtempfile = '/tmp/' . $time . 'dvctpwd';
/**
* $search generates replace target johndoe@example.com:{CRAM-MD5}479375185777b7ba573747c111483bdd628332a70268ce283dc80bedd0f65988
* if johndoe@example.com gives correct password to dovecot's doveadm pw -u johndoe@example.com -poldpassword
**/
$search = $argv[1] .':' . exec("doveadm pw -u " . $argv[1] . " -p" . $argv[2]);
/**
* $replace generates replace value johndoe@example.com:{CRAM-MD5}...
* i.e. scheme with new password
**/
$replace = $argv[1] .':' . exec("doveadm pw -u " . $argv[1] . " -p" . $argv[3]);
$command = <<<DD
sed -e "s|$search|$replace|" $passwd_file > $newtempfile && mv $newtempfile $passwd_file && echo "Password changed!\n";
DD;
$output = passthru($command);
echo $output . PHP_EOL;
【问题讨论】:
-
避免 sed 的“文件内”支持的一个原因是它不是真正的文件内; sed 使用临时文件模拟文件内行为,因此您唯一的好处是简化代码,而如果文件系统填满,或者可能还有其他情况,您会增加出现问题的风险。我喜欢编写几乎对每个命令都有错误处理的脚本,这样如果出现故障,我可以在脚本中采取适当的措施。
-
@ghoti 好点。我怀疑实际替换不是在文件本身中完成的,但无论如何我都在寻求尽可能简单的解决方案,因为我不是 BASH 语言的主人。