在Bash脚本中,sed命令无法正常工作

5

我已经搜索了数小时,寻找这个看似令人沮丧的简单问题的答案...

我有一个bash脚本,我已经简化了它以查找阻止它工作的那一行,现在只剩下:

#!/bin/bash
#
sed -i -e "s/<link>/\n/g" /usb/lenny/rss/tmp/rss.tmp

如果我运行这个脚本,对于文件rss.tmp没有任何变化-但是如果我从终端调用完全相同的sed命令,它会按预期进行所有替换。有人知道我在这里做错了什么吗?

2
我假设bash是您的交互式shell,PATH也相同(因此您正在运行相同的sed),等等?这个脚本对我来说很好用... - Nemo
echo $SHELL 应该会告诉你你的交互式 shell 是什么。 如果是 bash,请尝试在交互式 shell 和脚本中运行 type -a sed,查看它们是否相同。(或者直接使用 /bin/sed 而不是 sed,以避免搜索 PATH.)就像我说的,你的脚本对我来说很好用,所以这只是在徒劳地抓虫... - Nemo
2
最后一个想法是使用 #!/bin/sh -x#!/bin/bash -x 告诉 shell 打印它正在执行的字符... 嘿,我突然有个想法。你是否可能混淆了回车和换行符,以至于 "#" 开头的注释也消耗了你的命令? - Nemo
2
Nemo,这与回车符有关,所以谢谢你指点我方向!我一直在使用Windows下的Notepad++编辑脚本,当我查看所有字符时,回车符显示为cr/lf,因此我使用VI将它们全部更改,现在脚本按预期工作 :) - Jamie
1
DOS格式,@Nemo很聪明。下次你可以转换格式,比如dos2unix。 - chemila
显示剩余11条评论
4个回答

1

根据讨论,问题似乎是一个cygwin shell的问题。 问题在于shell脚本可能没有\r\n行终止符-它们需要\n终止符。早期版本的cygwin行为不同。 来自Cygwin FAQ的相关部分:http://cs.nyu.edu/~yap/prog/cygwin/FAQs.html

Q: shell脚本、.bashrc等出现神秘错误
A: 当bash读取您的.bashrc或.bash_profile时,您可能会收到神秘的消息,例如"\r command not found"(或类似消息)。当您去掉空行时,关于"\r"的投诉就会消失,但可能会有其他错误。发生了什么?
答案可能在于文本文件(也称为ASCII文件)可以以两种格式之一出现:DOS格式或UNIX格式。大多数编辑器都可以自动检测格式并在任何格式下正常工作。在DOS格式中,换行由两个字符表示:CR(回车或ASCII代码13)和LF(换行或ASCII代码15)。在UNIX格式中,换行只由一个字符LF表示。当读取您的.bashrc文件时,bash认为额外的字符是命令的名称,因此会出现错误消息。
在Cygwin或unix中,您可以通过调用以下命令将DOS格式的文件INFILE转换为Unix格式的文件OUTFILE:
> tr -d '\15' OUTFILE
注意: 如果您现在比较INFILE和OUTFILE中的字符数,您会发现后者已经丢失了正确的字符数(即INFILE中的行数):
> wc INFILE OUTFILE

既然我刚刚将这个问题/答案作为重复链接,我想补充一下,dos2unix实用程序(可以从Cygwin安装中获取)提供了一种舒适的方式来“杀死”文件中的DOS回车符,而无需经过tr的操作。 - DevSolar

0

试着使用那个代替:

sed -i -e "s/\<link\>/\n/g" /usb/lenny/rss/tmp/rss.tmp

-1

你需要提供一个输出文件,否则结果只会显示在屏幕上。

sed -e 's/<link>/\n/g' /usb/lenny/rss/tmp/rss.tmp > /usb/lenny/rss/tmp/output.tmp

-4

将文件传递给命令需要使用"<",而创建文件则需要使用">",据我所知sed通常用作文本格式化工具而非编辑器。也许可以尝试以下方式:

cat < /usb/lenny/rss/tmp/rss.tmp | sed -i -e "s/<link>/\n/g" > /usb/lenny/rss/tmp/rssedit.tmp

猫获取文件并使用sed编辑,输出到rssedit.tmp

然后检查rssedit.tmp是否包含所需内容

仅当它包含所需内容时

你的脚本的下一行应该是

mv /usb/lenny/rss/tmp/rssedit.tmp /usb/lenny/rss/tmp/rss.tmp 

这将用重命名为original替换made 1,并将其更名为original


不,sed -i 是直接修改文件。Jamie 的问题是脚本在行末有一个 CR,所以 sed 尝试访问一个名为 rss.tmpCR 的文件。 - Gilles 'SO- stop being evil'
格莱德(glead)已经修复了它,但是我写的是cat < /usb/lenny/rss/tmp/rss.tmp | sed -i -e "s/<link>/\n/g" > /usb/lenny/rss/tmp/rssedit.tmp这样他就可以看到rssedit.tmp是否有他想要的更改,然后使用mv /usb/lenny/rss/tmp/rssedit.tmp /usb/lenny/rss/tmp/rss.tmp将旧文件移动到新位置。 - nkvnkv

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