在 for 循环中使用正则表达式

在 for 循环中使用正则表达式

我希望循环遍历文件目录并将它们与正则表达式匹配,然后替换适当的字符:

#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

相关内容