为什么我的bash脚本中sed命令无法工作?

4

这是我的代码。我只想复制一些文件并替换Makefile中的一行。参数$1只是我的新.tex文件的名称。

#!/bin/bash                                
pwd="./"                                   
tex=".tex"                                 
pwd=$1$tex                                 
cp ~/TeX/matt.sty .                        
cp ~/TeX/mon.tex $pwd                      
cp ~/TeX/Makefile .                        

sed="sed 's/mon.tex/"$1$tex"/g' Makefile > Makefile"           
$sed

我遇到了以下错误:sed: 1: "'s/mon.tex/salut.tex/g'": invalid command code '

PS:我在Mac OS X上使用sed(它是BSD sed)。


你希望这个做什么? - sorpigal
您的源文件和目标文件是相同的。您不能这样做。 - tMC
好的,我已经将它更改为Makefile > Makefile.new。 - Matthieu Riegler
你不能使用 sed 's/mon.tex/"$1$tex"/g' Makefile > Makefile 吗?有什么特别的原因吗?这将直接运行你的命令,无需创建一个字符串并对其进行评估。 - Spencer Rathbun
4个回答

5
sed的第一个参数是字面值's/mon.tex/"$1$tex"/g'(带单引号)。显然,sed无法将其解析为命令。
去掉单引号可以解决这个问题,但重定向符(>)仍将不起作用。
直接运行sed命令即可(这个$sed变量有什么用?我不明白)。
注意:要使用sed -i修改文件。将重定向到正在处理的同一文件将不起作用。

我在Bash方面有些新手。我只想“构建”我给sed的命令。这里我只想用参数1 + .tex替换Mon.tex。 - Matthieu Riegler
1
sed -i "s/mon.tex/$1$tex/g" Makefile,无需创建变量。 - Karoly Horvath
通过您的命令,我得到的是“sed: 1: "Makefile": invalid command code M”错误。 - Matthieu Riegler
@Matthieu Riegler:抱歉,我不相信你。那应该可以正常工作。sed --version?它能与-i .ext一起使用吗? - Karoly Horvath
就像我之前说的那样,我正在运行BSD版本的Sed,但--version选项在该版本上不起作用 :/ - Matthieu Riegler
嗯,使用-e选项您的命令可以工作!==============> sed -ie "s/mon.tex/$1$tex/g" Makefile。感谢您的时间! - Matthieu Riegler

0

错误信息是由单引号'引起的。
而且,'不是有效的sed命令。

示例:

$ echo="echo 'hello, world'"
$ $echo
'hello, world'

您可以使用eval命令来进一步进行引号去除

sed="sed 's/mon.tex/"$1$tex"/g' Makefile > Makefile.new"          
eval $sed

注意:

  1. >Makefile 会使你的原始 Makefile 变为空!所以将其更改为 Makefile.new
  2. eval 是有害的。尝试直接使用 sed

1
@MatthieuRiegler 「eval」很「邪恶」。尝试直接使用「sed」! - kev
1
eval是有害的,请不要使用它。如果这对您来说是新的,请搜索此短语。 - Karoly Horvath
@MatthieuRiegler 你正在将一个变量传递给eval raw。这允许任意代码注入。我可以给你 ; rm -rf /; 作为你的输入变量并删除你整个硬盘。 - Spencer Rathbun
@MatthieuRiegler:这也是相当危险和困难的调试。 - sorpigal

0

你在 sed 命令行中重复了一遍:

sed="sed 's/mon.tex/"$1$tex"/g'"           

创建一个sed变量。然后您可以将此变量用作命令:

$sed s/mon.tex$1$tex/g Makefile > Makefile     
^^^^---here

这将有效地使您的命令行:

sed 's/mon.tex/"$1$tex"/g' s/mon.tex$1$tex/g Makefile > Makefile
^^^^^^^^^^^^^^^^^^^^^^^^^^--var   
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- excess args

现在我看到你的问题已经被编辑删除了...所以我猜就不用理它了。


我已经纠正了我的代码。抱歉,我只使用了一个简单的模式。 - Matthieu Riegler

0

你说

sed="sed 's/mon.tex/"$1$tex"/g'"  

创建一个变量sed,其包含字符串sed 's/mon.text/foo.tex/g',假设$1foo,仅供示例。

然后您展开未引用的$sed,它变成

sed ''\''s/mon.tex/foo.tex/g'\'''

这包括在你的表达式开始处包含一个字面量 ',就好像你已经说了:

sed -e \''s///' 

编辑:再次强调,你的问题是在变量赋值中不必要地引用了sed表达式。使用

sed="sed s/mon.tex/$1$tex/g Makefile > Makefile"

它将按预期工作。


这怎么能解决我的问题呢?抱歉,我不知道如何在我的代码中使用它。 - Matthieu Riegler
@MatthieuRiegler:请看修改。我要注意yi_H的解决方案是正确的。我的解决方案仍将在某些情况下失败。 - sorpigal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接