简单的sed替换

0 人关注

我有一个文本文件,其中有一个结构为ABC123456A或ABC123456AA的文件列表。我想做的是检查文件ABC123456ZZP是否也存在,即我想用ZZP代替ABC123456后面的字母。

我可以用sed做这个吗?

linux
sed
awk
csh
moadeep
moadeep
发布于 2013-01-14
3 个回答
wilx
wilx
发布于 2013-01-14
已采纳
0 人赞同

Like this?

X=ABC123456 ;  echo ABC123456AA | sed -e "s,\(${X}\).*,\1ZZP,"
    
正是这样。非常感谢
这是错误的方法,因为它效率低下,对各种文件名都会失败。
文件名是自动生成的,有相同的格式,3个字母,后面是2个数字(年份),然后是4个数字,从0000到9999递增。后面的字母可以不同,但它们并不重要,只要我能够访问前9个字符即可。
那么正确的方法可以参考@peteches或我的回答。用管道连接到sed是错误的方法,充其量是比正常的shell解决方案效率低,如果你真的想用管道连接到什么东西来获取前9个字符,那么就用管道连接到 cut -c1-9 ,因为那会比使用sed更有效、更强大。但我还是不会这样做,因为shell的内置程序工作得很好。
peteches
peteches
发布于 2013-01-14
0 人赞同

你可以按照wilx的建议使用sed,但我认为更好的选择是bash。

while read file; do
    base=${file:0:9}
    [[ -f ${base}ZZP ]] && echo "${base}ZZP exists!"
done < file

这将循环处理文件中的每一行 然后base被设置为该行的前9个字符(不包括空白)。 然后检查是否存在一个在基数末尾带有ZZP的文件,如果存在则打印一条信息。

对于包含空格、反斜线等的文件名,这将会失败,所以虽然它可能对OP的例子有效,但一般来说是错误的。
当然,在一般情况下,这需要一个专门的函数来处理路径,以确保元字符空格和其他奇怪的东西被转义,但当你被赋予一个特定的文件名格式时,这将是不必要的。
你不需要一个专门的函数,只要使用 "read"( IFS= read -r )的正确形式。这样做并没有明显的难度,而且可以避免你在以后的工作中自寻烦恼。
Ed Morton
Ed Morton
发布于 2013-01-14
0 人赞同

Look:

$ str="ABC123456AA"
$ echo "${str%[[:alpha:]][[:alpha:]]*}"
ABC123456

so do this:

while IFS= read -r tgt; do
    tgt="${tgt%[[:alpha:]][[:alpha:]]*}ZZP"
    [[ -f "$tgt" ]] && printf "%s exists!\n" "$tgt"
done < file

对于含有换行符的文件名,它仍然会失败,所以如果你有这种情况,请让我们知道,但与其他发布的解决方案不同,它对含有9个以上关键字符的文件名、含有空格、逗号、反斜线、globbing字符等的文件名都能工作,而且效率很高。

既然你现在说你只需要每行的前9个字符,而且你对每行都用管道输入sed感到满意,这里有另一个你可能喜欢的解决方案。

cut -c1-9 file |
while IFS= read -r tgt; do