我想使用sed执行以下操作:
<id>aa123</id>
。每个nfo都有多行(但只有一个id)。http://www.domain.com/title/aa123
。http://www.domain.com/title/aa123
。我设法拼凑了一些有效的东西,但是当这个脚本找不到id字符串时(因为并非所有的nfo文件都有),我最终得到一个空的nfo文件。我该如何防止这种情况?
find /home/me/Documents -name \*.nfo -exec sed -i'.bak' -r -e '/<id>(aa[0-9]+)<\/id>/!d' -e 's/<id>(aa[0-9]+)<\/id>/http:\/\/www.domain.com\/title\/\1/' {} \;
答案 0 :(得分:3)
您必须避免在没有匹配项的文件上运行sed
。您可以使用运行-exec
的额外grep
执行此操作;如果grep
具有非零退出状态,则-exec
主要版本将失败,并且不会检查该文件的其余原色。 (注意:任何想象力都无效。)
find /home/me/Documents -name '*.nfo' \
-exec grep '<id>aa[0-9]+</id>' {} \; \
-exec sed -i'.bak' -r \
-e '|<id>(aa[0-9]+)</id>|!d' \
-e 's|<id>(aa[0-9]+)</id>|http://www.domain.com/title/\1|' {} \;
如果它仍然不起作用,这里是上面不可读的单行版本:
find /home/me/Documents -name '*.nfo' -exec grep '<id>(aa[0-9]+)</id>' {} \; -exec sed -i'.bak' -r -e '|<id>(aa[0-9]+)</id>|!d' -e 's|<id>(aa[0-9]+)</id>|http://www.domain.com/title/\1|' {} \;
答案 1 :(得分:2)
这是一个最低限度修改的命令版本,可以单独处理不匹配情况。此方法的优点是您不必检查文件两次,以了解它们是否包含您要查找的表达式。 sed
的输出已包含该信息,您正在进行备份,因此:
find . -name \*.nfo \ -exec sed -i'.bak' -r -e '/<id>(aa[0-9]+)<\/id>/!d' \ -e 's/<id>(aa[0-9]+)<\/id>/http:\/\/www.domain.com\/title\/\1/' {} \; \ -empty -exec mv '{}'.bak '{}' ';'
粗体细分将检查原始文件是否为空,并将其替换为sed
所做的备份。这只会发生在不匹配的情况下,因此修改后的文件将保持原样。
这取决于find
通常重新排列测试的事实,但将按指定的顺序保留命令的含义。从手册页:
查找程序重新排序测试以加快执行速度,同时保持整体效果;也就是说,副作用的谓词不会相对于彼此重新排序。
在这种情况下,-exec
会产生副作用,因此无论进行何种优化,都会在-empty
运行后检查sed
。修改后的文件永远不会为空,因此mv
在这种情况下不会运行。