我希望循环遍历文件目录并将它们与正则表达式匹配,然后替换适当的字符:
#somefile.txt
%somefile.txt
>somefile.txt
# arr=(\% \> \#) ;for f in *; do echo -- "$f" "${f//${arr[@]}/}"; done
应该回显:
#somefile.txt -- somefile.txt
%somefile.txt -- somefile.txt
>somefile.txt -- somefile.txt
相反,我得到:
#somefile.txt -- #somefile.txt
%somefile.txt -- %somefile.txt
>somefile.txt -- >somefile.txt
这不会导致任何改变,nada,zilch。
arr(\%)
如果我使用单个字符,该数组就可以工作,这违背了整个目的。
#somefile.txt -- #somefile.txt
%somefile.txt -- somefile.txt
>somefile.txt -- >somefile.txt
答案1
这里的核心问题是${PARAMETER/PATTERN/STRING}
扩展PATTERN
不接受数组PARAMETER
,因此${arr[@]}
扩展为"% > #"
.
如果添加几个文件就可以看到效果:
# touch "% > #somefile.txt"
# touch "%>#somefile.txt"
您的命令将导致:
#somefile.txt -- #somefile.txt
%somefile.txt -- %somefile.txt
>somefile.txt -- >somefile.txt
%>#somefile.txt -- %>#somefile.txt
% > #somefile.txt -- somefile.txt
最后一行希望准确地显示正在发生的事情。
另一个人建议使用管道$f
通过sed
并在那里做魔术,这将是一个不错的选择,因为它允许更复杂的转换,但是假设您只想删除前导字符,使用 bash${PARAMETER#WORD}
参数扩展就足够了:
# gpat=" ;for f in *; do echo -- "$f" "${f#$gpat}"; done
对于我自己来说,这条线的结果是:
>somefile.txt -- somefile.txt
#somefile.txt -- somefile.txt
%somefile.txt -- somefile.txt
%>#somefile.txt -- >#somefile.txt
% > #somefile.txt -- > #somefile.txt
我将这种模式称为$gpat
“a”bash 通配符模式。它是不是一个正则表达式。
请注意,它${PAR#WORD}
是非贪婪的,并且匹配最短的可能模式 -${PAR##WORD}
匹配最长的可能模式。然而,对于gpat="[%>#]"
,无论如何都只会匹配一个字符:
# gpat="[%>#]" ;for f in *; do echo "$f" -- "${f##$gpat}"; done
%somefile.txt -- somefile.txt
>somefile.txt -- somefile.txt
#somefile.txt -- somefile.txt
%>#somefile.txt -- >#somefile.txt
% > #somefile.txt -- > #somefile.txt
如果我们extglob
设置了 shell 选项(检查 with shopt extglob
、设置 with shopt -s extglob
、取消设置 with shopt -u extglob
- 如果你有合理的 ,则可能已设置bashrc
),我们可以使用扩展的通配模式:
# gpat="+([%>#])" ;for f in *; do echo "$f" -- "${f##${gpat}}"; done
%somefile.txt -- somefile.txt
>somefile.txt -- somefile.txt
#somefile.txt -- somefile.txt
%>#somefile.txt -- somefile.txt
% > #somefile.txt -- > #somefile.txt
但值得注意的是,在上述所有示例中,由于 % 后面的空格未被模式捕获而导致"% > #somefile.txt"
。" > #somefile.txt"
当然,${PARAMETER/PATTERN/STRING}
(和//
类似的)也接受通配模式,但我只是在输入这些单词时才意识到这一点(字面意思),而且我真的懒得回顾上面的内容来调整它以反映这一点。不管怎样,它的工作原理完全相同,当然您只想用来PAR/PAT/
删除字符串中间的字符。
答案2
这似乎对我有用......
$ ls
#somefile.txt %somefile.txt >somefile.txt
$ for f in *; do j=`echo $f | sed -e's/[\%\#\>]//g'`; echo "$f -- $j"; done
#somefile.txt -- somefile.txt
%somefile.txt -- somefile.txt
>somefile.txt -- somefile.txt