无法为 grep 或两个正则表达式


我想编写一个 bash 脚本,根据文件的修改日期查找文件。 例如,此./find_by_date Jul

应输出在 7 月修改的所有文件,此./find_by_date 8应输出在每月 8 日修改的所有文件。find_by_date Jul 8应该找到7 月 8日修改的所有文件

这是我到目前为止尝试过的:

#!/usr/bin/env bash
function find_by_date
{
date=$1;
date=${date:?'missing'};
echo $(ls -l | grep -i "(.{37}$date|.{40}$date)" | cut -c51-);
}
find_by_date $1

但是,grep 的正则表达式无法正常工作。 如果我只使用.{37}$date.{40}$date,它可以工作。 但是如果我or它们,它就不起作用。

任何人都可以帮我处理正则表达式吗?

更新 1

按照建议,我将正则表达式更改为:

grep -i -E ".{37}$date|.{40}$date"

仍然不起作用。

更新 2

这是我运行测试的目录:

-rw-r--r-- 1 fatemeh fatemeh     231 Jul  8 19:48 albums.txt
-rw-r--r-- 1 fatemeh fatemeh      47 Jul  8 19:43 alice
-rw-r--r-- 1 fatemeh fatemeh 2540187 Aug  8 00:26 output.txt
-rwxrwxr-x 1 fatemeh fatemeh     178 Aug  8 23:55 p102_ex.sh
-rwxrwxr-x 1 fatemeh fatemeh     349 Aug  4 20:53 p92_ex.sh
-rwxrwxr-x 1 fatemeh fatemeh     330 Jul  7 23:55 p97_ex.sh
-rwxrwxr-x 1 fatemeh fatemeh      98 Aug  8 00:33 p98_ex.sh
-rwxrwxr-x 1 fatemeh fatemeh     255 Aug  9 00:35 stack.sh
-rw-rw-r-- 1 fatemeh fatemeh     720 Aug  8 00:05 test.py
-rwx-wx--x 1 fatemeh fatemeh     207 Aug  1 11:58 test.sh
-rw-r--r-- 1 fatemeh fatemeh       0 Aug  7 00:24 tmp.txt

./find_by_date Jul的输出必须为:albums.txt alice p97_ex.sh(7月全部修改(

./find_by_date 7的输出必须是:p97_ex.sh tmp.txt

./find_by_date Aug 8的输出必须是:output.txt p102_ex.sh p98_ex.sh test.py

您必须注意,应避免解析ls和其他实用程序的输出,因为UNIX风格甚至版本之间的格式的细微变化会使shell功能无法使用。

无论如何,对于您的程序,您可以编写|而不仅仅是正则表达式中的|

当你使用不带-Egrep时,它使用POSIX"基本"正则表达式语法。在此语法中,括号、大括号、条形(交替(、加号和问号都是没有特殊含义的普通字符。大括号(有时是部分/全部其他括号(可以通过转义来赋予它们通常的正则表达式含义。如果您的grep版本支持转义栏括号,则可以使用:

grep -i "(.{37}$date|.{40}$date)"

(请注意,括号和栏是转义的。但最好使用grep -E,它调用"扩展"正则表达式语法,其中这些字符具有其特殊含义,除非它们被转义。此版本将是:

grep -Ei "(.{37}$date|.{40}$date)"

(请注意,此处的花括号已被删除。

但这里还有其他一些问题。首先,正则表达式根本没有锚定,因此第一个分支将匹配字符串中至少$date37个字符的任何出现(因为 37 个字符不必从行首开始(。如果希望它正好匹配 37 个字符,请将^添加到表达式的前面,以将其锚定到行的前面。

其次,你的脚本只看它的第一个参数($1(,所以find_by_date Jul 8会完全忽略"8"。您可以将所有参数与"$*"合并,但这只会用空格分隔参数,ls通常打印例如 7 月 8 日,它们之间有两个空格。你必须使用这样的东西来构建一个模式:

function find_by_date
{
datepattern=$1
shift
for arg in "$@"; do
datepattern+=" +$arg"    # " +" will match one or more spaces
done
...
find_by_date "$@"    # "$@" will pass on *all* arguments

但最重要的是ls其输出格式并不那么一致。列宽可能因字段的内容而异,因此在特定列中查找日期(并期望文件名从第 51 列开始(充其量是一件有趣的事情。你最好使用类似的东西stat,您可以在其中控制输出格式。

(不幸的是,最后一点使其他人大多没有意义。你真的需要改变整体方法。

最新更新