<p>你的问题是:</p>
<pre><code>old_val=3 sed "s/$old_val/$new_val/g"
</code></pre>
<p>依赖于shell来扩展变量,而不是<code>sed</code>。但是通过命令前缀设置变量只会影响命令的环境,而不是bash,因此<code>old_val</code>是<em>从不</em>为字符串插值而定义的。根据<a href="https://www.gnu.org/software/bash/manual/bash.html#Environment" rel="nofollow noreferrer">bash reference manual</a>(加上强调):</p>
<blockquote>
<p>The environment for any simple command or function may be augmented temporarily by prefixing it with parameter assignments, as described in Shell Parameters. These assignment statements affect <em>only</em> the environment seen by <em>that command</em>.</p>
</blockquote>
<p>因此,如果<code>sed</code>试图从自己的环境中读取<code>old_val</code>,它将看到正确的值。但是<code>sed</code>接收的是传递的后插值字符串,它是<code>s//9/g</code>,因为bash插值没有看到<code>old_val</code>(它只存在于<code>sed</code>)。在</p>
<p>要修复此问题,请在bash中设置变量,方法是将赋值作为单独的命令执行,而不是<code>sed</code>前缀:</p>
^{pr2}$
<p>或者更准确地说,您应该真正避免依赖<code>shell=True</code>(这很危险/很容易被滥用)。即使必须使用<code>sed</code>,也可以在Python层完成使用shell的所有工作:</p>
<pre><code>import os
# Get the (unqualified) names of all the entries with the desired name
files = [f for f in os.listdir('/etc/squid') if f.endswith('.conf')]
# Run w/o shell=True, in list form, letting Python handle the working directory
# and variable formatting
subprocess.Popen(['sed', '-i', 's/{}/{}/g'.format(old_val, new_val)] + files, cwd='/etc/squid')
</code></pre>
<p>这有相同的行为(在<code>/etc/squid</code>中操作,并传递不合格的文件名,这样如果在深度嵌套的目录中有很多文件,就不会出现新的命令行长度问题)。在</p>
<p>当然,您可以更进一步,只需在Python中使用<a href="https://docs.python.org/3/library/fileinput.html" rel="nofollow noreferrer">the ^{<cd13>} module</a>来完成<code>sed</code>的工作;它的特点是像<code>sed</code>一样就地编辑文件(尽管如果文件的大小有意义,它可能会稍微慢一点)。在</p>