我刚开始学习正则表达式,想用它代替其他地方的其他人进行练习。
我在尝试查找带有扩展名的文件时遇到这种情况 sh or md
$ find . regex ".*\.(sh|md)$"
.
./bogus.py
./cofollow.py
./data8.txt
./example.sh
./longest_word_2.sh
./posit_param.sh
./cobroadcast2.py
Run Code Online (Sandbox Code Playgroud)
不幸的是它输出/bogus.py
,
我注意到 BRE 规则并尝试逃跑 ()
$ find . -regex ".*\.\(sh|md\)$"
#get nothing return
Run Code Online (Sandbox Code Playgroud)
经过一系列的搜索,我得到了 -regextype 解决方案正则表达式 - 查找文件
$ find . -regextype posix-extended -iregex ".*\.(sh|md)$"
./example.sh
./longest_word_2.sh
./posit_param.sh
$ find . -regextype egrep -iregex ".*\.(sh|md)$"
./example.sh
./longest_word_2.sh
./posit_param.sh
./table_regex_bat.md
Run Code Online (Sandbox Code Playgroud)
此外,一个不错的模块化解决方案
$ find -type f | egrep ".*\.(sh|md)$"
./example.sh
./longest_word_2.sh
./posit_param.sh
./table_regex_bat.md
Run Code Online (Sandbox Code Playgroud)
然而,在 BSD 中有一个快捷方式可以用-E
谓词完成这样的任务。
$ /usr/bin/find -E . -regex ".*\.(sh|md)$"
./example.sh
./longest_word_2.sh
./posit_param.sh
Run Code Online (Sandbox Code Playgroud)
我决心专门采用 GNU 工具,以使我的代码和技能可移植。
所以我开始给'find -regextype egrep`取别名,
不幸的是找到$1作为路径。
我怎样才能以方便的方式解决他们的问题?
不要使用 analias
来传递参数。它们不可移植且仅在交互式 shell 上有用。改用函数并将参数作为需要的路径传递
regexFind() {
(( "$#" )) || { printf 'Insufficient arguments provided \n' >&2; return 1; }
find "$1" -regextype egrep -iregex ".*\.(sh|md)$"
}
Run Code Online (Sandbox Code Playgroud)
并将函数调用为
regexFind "/home/foo/bar"
Run Code Online (Sandbox Code Playgroud)
另外要添加到您的发现中,请注意,它bash
也具有 glob 文件的内在方式。您只需要启用几个扩展的 shell 选项即可使其工作。在-s
启用选项并-u
禁用它。
在nullglob
允许忽略未膨胀的水珠结果有效的匹配。因此,假设您想匹配以*.sh
and结尾的文件*.md
,您只需要导航到该特定目录并执行
shopt -s nullglob
fileList=(*.sh)
fileList+=(*.md)
shopt -u nullglob
Run Code Online (Sandbox Code Playgroud)
并打印结果以查看下文。请记住引用扩展以防止文件名进行分词。
printf '%s\n' "${fileList[@]}"
Run Code Online (Sandbox Code Playgroud)
请注意, GNUfind
的默认正则表达式不是 BRE,而是来自某些古老版本的 GNU 的正则表达式emacs
(BRE 和 ERE 之间的某种混合体,例如,+
受支持,但您需要\(...\)
并且|
受支持,但作为\|
)。
对于 BSD find
,默认值为 BRE,您可以使用该-E
选项来启用 ERE,因此,只需执行以下操作:
alias efind='find -E'
Run Code Online (Sandbox Code Playgroud)
或者:
efind() { find -E "$@"; }
Run Code Online (Sandbox Code Playgroud)
在 GNU 中find
,启用 ERE 是通过-regextype posix-extended
谓词而不是选项来实现的。该谓词必须出现在文件名之后,如果存在,则必须出现在选项之后和使用它们的-regex
或之前。-iregex
GNUfind
语法是:
find [options] [files] [predicates]
^
Run Code Online (Sandbox Code Playgroud)
所以你需要将其插入那里(标有 的位置^
)。
因此,在定义包装函数或脚本时,您需要考虑到这一点:跳过所有选项和文件名并-regextype posix-extended
在它们后面插入。
efind() (
found_predicate=false
for arg do
"$found_predicate" || case $arg in
(-[LPDd]|-[OD]*) ;; # skip options
(-*|['()!'])
set -- "$@" -regextype posix-extended
found_predicate=true;;
esac
set -- "$@" "$arg"
shift
done
exec find "$@"
)
Run Code Online (Sandbox Code Playgroud)
其他一些注意事项:
bogus.py
不是因为使用了 BRE,而是因为您使用regex
了-regex
. regex
被视为文件名,而不是谓词。find . | egrep ...
无效,因为文件路径可能由多行组成。使用 GNU 工具或兼容工具,您可以处理find . -print0 | grep -zE ...
NUL 分隔的记录(tr '\0' '\n'
如果用于显示,则可以通过管道传输到)。