正则表达式以开头和结尾

时间:2016-11-29 16:06:34

标签: regex git terminal

我正在尝试使用git运行搜索,以便在两个文件夹之一中获取所有暂存文件:本地或组件。我只想获得JS文件。该命令在控制台中运行。

到目前为止我所拥有的:

STAGED_FILES=($(git diff --cached --name-only --diff-filter=ACM | grep "^(local|components).*?.js"))

这会让我获得所有暂存的文件:

git diff --cached --name-only --diff-filter=ACM 

这将获取以本地或组件

开头的所有文件路径
grep "^(local|components)"

这让我得到所有js文件

grep ".js"

由于某种原因,这并没有让我失望:

($(git diff --cached --name-only --diff-filter=ACM | grep "^(local|components).*?.js"))

我可以使用哪个正则表达式来获取这两个文件夹中的所有js文件?

2 个答案:

答案 0 :(得分:4)

它无效,因为grep不支持?懒惰匹配。您可以使用-E来扩展正则表达式。

例如考虑这些

$ echo "asfasdfzasdfasdfz" | grep -E "a.*?z"
asfasdfzasdfasdfz
$ echo "asfasdfzasdfasdfz" | grep  "a.*?z"
$ echo "asfasdfzasdfasdf?z" | grep  "a.*?z"
asfasdfzasdfasdf?z

如您所见,没有-E它会尝试在字符串中匹配?

答案 1 :(得分:2)

除了基于正则表达式的答案之外,您可以直接在Git中执行此操作,Git具有" pathspec"的概念。包括shell样式通配:

git diff --cached --name-only \
    --diff-filter=ACM -- 'local/**/*.js' 'components/**/*.js'

(为了显示格式而中断了行;请注意,**支持是Git版本1.8.2中的新功能。)

那就是说,正则表达式更强大"比shell globs,所以你可能想要记住nu11p01n73R's answer。但请注意,非贪婪匹配(*?)尽可能匹配 little ,而不是尽可能

pattern       input      result (matched part in parentheses)

abc.*e     0abcdefeged        0(abcdefege)d
abc.*?e    0abcdefeged        0(abcde)feged
abc.*d     0abcdefeged        0(abcdefeged)
abc.*?d    0abcdefeged        0(abcd)efeged

你的表达式^(local|components).*?.js表示(无论如何扩展解释):匹配行的开头;然后将localcomponents匹配为文字文字;然后匹配尽可能少的字符,也许没有;然后匹配任何角色;然后匹配文字j;然后匹配文字s。因此,这与local-jaguar-xjs-vehicles匹配,因为它以local开头,包含一些文字,在js之前有一个字符,并继续。

shell glob模式local/**/*.js仅匹配目录 local,后跟任何数量 - 可能为零的子目录组件,后跟名为的文件以 .js结束,点与字面匹配。所以这相当于模式^local/(.*/|)[^/]*\.js$:文本文本local在行的开头匹配,后跟一个斜杠;接下来是:以斜线结尾的任意数量的字符(尽可能多地占用),或者根本没有;后跟除斜杠之外的任何字符的任何数字(包括无),后跟文字.js,后跟行尾。

请注意,因为此表达式锚定在两端(必须在开头行的末尾匹配),并且中间只有一个Kleene star,所以无关紧要我们是使用贪婪还是非贪婪的匹配:左侧的左侧锚点匹配,右侧的左侧锚点匹配,贪婪的匹配尽可能多地占据中间位置,即全部匹配 - 虽然非贪婪的比赛需要中间的,因为它可以...... 仍然"所有这些"。

(当然,这确实假设每行只打印一个文件名。幸运的是git diff --name-only就是这样做了。另外,shell **代表"任何数字所有shell中都不支持目录",并且所有非shell文件名都不支持globbing,但是 在Git' s pathspecs中使用(搜索" pathspec"))