将“find -regextype egrep”设为别名

Abs*_*cDo 4 bash

我刚开始学习正则表达式,想用它代替其他地方的其他人进行练习。

我在尝试查找带有扩展名的文件时遇到这种情况 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作为路径。

我怎样才能以方便的方式解决他们的问题?

Ini*_*ian 7

不要使用 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允许忽略未膨胀的水珠结果有效的匹配。因此,假设您想匹配以*.shand结尾的文件*.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)


Sté*_*las 5

请注意, 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'如果用于显示,则可以通过管道传输到)。