我有一个如下所示的shell脚本:
#!/bin/bash
for file in $1/*.html; do
echo "Working on $file ..."
# delete headers in html files.
sed -n '1,9d' $file
# delete the last 4 lines of the file.
sed -n -e :a -e '1,4!{P;N;D;};N;ba'
# ant runs regex task on all apt files
ant -Dtarget.file=$file
# all .html are changed to .md
mv $file `echo $file | sed 's/\(.*\.\)html/\1md/'` ;
done
但脚本挂在第一个sed命令上,我必须强行退出。我想知道我的设置方式是否有任何不妥之处?
如果我删除前两个sed命令,我可以运行脚本的其他部分,包括最后一个带有sed命令的部分。
答案 0 :(得分:4)
我认为你会发现它挂在 second sed
上,你不提供文件名来处理。换句话说,它将从终端获取其标准输入。
您将无法从第一个sed
获得输出,因为-n
会阻止默认打印模式空间。如果您尝试更改实际的文件而不是将更改输出到标准输出,则需要-i
inplace编辑器。
如果您无法使用inplace选项,则必须执行以下操作:
sed -n '1,9d' ${file} >${file}.tmp0
sed -n -e :a -e '1,4!{P;N;D;};N;ba' ${file}.tmp0 >${file}
rm -f ${file}.tmp0
这使用临时文件进行更改,但最后一次更改除外,它会覆盖原始文件。请注意,此更改原件 - 如果这不是您想要的,您可以将第二个sed
更改为输出到${file}.tmp2
,但您必须调整后续版本命令将其考虑在内。
如果您确实要删除文件的前九行和后四行,您还可以使用以下内容:
head --lines=-4 oldfile.txt | tail --lines=+10 >newfile.txt
如果您[rd]ecent
实施head/tail
。 head
打印除最后四行之外的所有行,tail
开始在第十行打印。
答案 1 :(得分:0)
你在运行什么命令?如果没有任何内容匹配文件glob,那么它将在那里物理插入未扩展的字符串。
例如,试试这个:
$ for i in foo/*.bar; do echo $i; done
foo/*.bar
所以你的sed脚本正在轰炸,因为它接收的文件名不存在,这意味着它将表现为没有指定文件参数(即stdin)。
答案 2 :(得分:0)
将第一行更改为:
#!/bin/bash -x
在所有扩展完成后,这将显示每个命令,因为bash执行它。
我的猜测是$1/*.html
与任何文件都不匹配;因此sed行评估为sed -n '1,9d'
,所以sed试图从stdin读取