我正在尝试使用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文件?
答案 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
表示(无论如何扩展解释):匹配行的开头;然后将local
或components
匹配为文字文字;然后匹配尽可能少的字符,也许没有;然后匹配任何角色;然后匹配文字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"))