输入如下: Content-Disposition: form-data; name="test.png"; filename="test.jpg" 或 Content-Disposition: form-data; name="foo"
输出: ['test.png', 'test.jpg'] 或 ['foo']
哪位大佬指导下?[献花][献花][献花]
![]() | 1 creanme 2020-07-04 23:18:38 +08:00 via Android 手机回复的,也没测试,就当瞎写的。 name=(".*\.png");filename=(".*\.jpg") 用$1 与$2 输出 |
![]() | 2 mingl0280 2020-07-04 23:20:54 +08:00 (\")(\S+)(\")取第二组。 |
![]() | 3 mingl0280 2020-07-04 23:21:31 +08:00 https://regex101.com/ 这个网站可以直接测试正则,挺好用的。 |
4 aheadin 2020-07-04 23:25:27 +08:00 ![]() function(str) { return [...str.matchAll(/name="([\w+.]+)"/g)].map(item => item[1]) } |
5 supermoonie OP @mingl0280 /(?:")(\S+)(?:")/.exec('Content-Disposition: form-data; name="test.png"; filename="test.jpg"') 稍微改了下,返回的是 [""test.png"", "test.jpg"],第一个多了双引号。。。 |
6 supermoonie OP @aheadin niubility,大佬能一个正则匹配出来吗? |
7 supermoonie OP @creanme 第二种情况满足不了 |
8 ochatokori 2020-07-04 23:45:02 +08:00 js 的正则最简单了,挖空填入(.*?)就好了 ```Javascript text.match(/name="(.*?)"(.*?)filename="(.*?)"/) // 取数组的 1 和 3 如果想第二种情况节 /name="(.*?)"/ ``` |
![]() | 9 autoxbc 2020-07-04 23:45:50 +08:00 ![]() 正则就是圣杯,不管什么问题搞成正则就对了 <-- 害人不浅 |
10 sedgwickz 2020-07-04 23:47:06 +08:00 ![]() 'Content-Disposition: form-data; name="test.png"; filename="test.jpg" 或 Content-Disposition: form-data; name="foo"'.match(/(?<=(name\="|filename\=")).*?(?=")/g) |
11 supermoonie OP @ochatokori 分开写,我也会,我在尝试一个正则怎么给取出来,貌似有点难。。。 |
12 lidlesseye11 2020-07-04 23:50:35 +08:00 。。。你这个需求不就是取引号里的东西吗? |
13 supermoonie OP @sedgwickz niubility,大佬一出手就知有没有 |
14 supermoonie OP @lidlesseye11 是的呢,目前只看到一位大佬写出来了,小弟反正是写不出来 |
15 lidlesseye11 2020-07-05 00:11:43 +08:00 @supermoonie 那 split 比较简单粗暴吧。。 function getName(str) { var arr = str.split("\""); var rtnArr = new Array(); for(var i = 0;i < arr.length; i++) { if (i%2!=0) rtnArr.push(arr[i]); } return rtnArr; } |
16 supermoonie OP @lidlesseye11 你不觉得 /(?<=(name="|filename=")).*?(?=")/g 这个正则很完美吗?( emmm... 主要是项目是自己的,所以自己能看懂就行了,虽然我知道 split 更直接更易读,但是一旦有了想用正则去做,就会不死不休) |
![]() | 17 mingl0280 2020-07-05 00:27:07 +08:00 @supermoonie 正则匹配下来应该是个 iterator 啊,你在想啥 ``` var str = 'Content-Disposition: form-data; name="test.png"; filename="test.jpg"' var matches = str.matchAll(/(")(\S+)(")/g) for(const match of matches) { console.log(`${match[2]}`) } ``` |
![]() | 18 xiaoming1992 2020-07-05 00:29:31 +08:00 const str = "" const reg = /(?<=name=\")(.+?)(?=\")/g let exec = reg.exec(str) const resultArray = [] while (exec) { __resultArray.push(exec[0]) __reg.exec(str) } |
19 supermoonie OP @mingl0280 想的是一行代码搞定,有就返回['test.png', 'test.jpg'] 或者 ['foo'] ,没有就返回 null,/(?<=(name="|filename=")).*?(?="\s+)/g 这个正则不是更香吗? |
20 supermoonie OP @xiaoming1992 谢了,前面有位大佬提供了 /(?<=(name="|filename=")).*?(?="\s+)/g |
![]() | 21 alan0liang 2020-07-05 09:14:07 +08:00 via Android 略微有点偏题: https://alf.nu/RegexGolf |
22 justgodlike1993 2020-07-05 10:25:42 +08:00 "[^"]*?" |
![]() | 23 no1xsyzy 2020-07-05 14:47:57 +08:00 |
![]() | 24 no1xsyzy 2020-07-05 15:07:19 +08:00 对了,/(?<=(name="|filename=")).*?(?="\s+)/g 有若干问题 1. lookbehind 在 Firefox < 78 不可用(参考: https://caniuse.com/#feat=js-regexp-lookbehind ),这个主题让我发现我该更新了。更新到 78 就可用了;另外 #3 似乎会根据浏览器版本来改变 Javascript 下的效果(或者是因为就是用的浏览器实现)。 2. (?="\s+) 严格要求 lookahead 是一个引号和至少一个空白符。而你的第一个输入中,test.png 后面是 "; 一个引号一个分号,也就不会被获取,应该改成 (?=") (我发现你过了十分钟后的回复多了 \s+ ) 3. 不要 capturing group 不需要的部分,应该用 non-capturing group 。 4. 如果是 Perl 下面,lookbehind 要求宽度一致。name="|filename=" 宽度不一致。 |
![]() | 25 no1xsyzy 2020-07-05 15:10:07 +08:00 另外,根据上述 caniuse 你这个正则只有在 71% 左右的浏览器上可运行。 Safari 全灭。 |
26 supermoonie OP @no1xsyzy 后来多的 \s+ 是我自己加上去做测试的,忘记去掉了。前端的兼容性问题真是让人脑壳疼,没想到一个正则,各家浏览器支持竟然不一样,感谢大佬科普!由于是项目初期,先保证在 Chrome 能正常使用,所以兼容性目前不是考虑的重点,后期会不停迭代进行优化。(想尽早出一个版本,一个人的精力有限) |
![]() | 27 jiejiss 2020-07-05 20:43:20 +08:00 1. 请写 string parser,你这个需求用正则带来的心智负担更大 2. 正则不是银弹,不是所有情况下都要用正则 3. 想练手可以去 https://www.hackerrank.com/domains/regex,想进阶可以去 https://alf.nu/RegexGolf 4. https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags |
28 supermoonie OP @no1xsyzy 现在我能想到的最简单的正则就是 /"([^;]*)"/g 这个了,匹配到的结果再把双引号给 replace 掉。。。大佬有好的思路吗? |
29 supermoonie OP @jiejiss 个人项目,一开始只是想用正则试下,发现这个正则不是太好写,就来问问各位大佬,扩展下思路,学习了[抱拳] |
30 supermoonie OP @justgodlike1993 用的这个 /"([^;]*)"/g 正则,最后再把双引号 replace 掉 |
![]() | 31 no1xsyzy 2020-07-05 22:41:15 +08:00 发现之前写完了没发( @supermoonie #28 /"([^"]*)"/g 然后拿 group 1 。反正文件名带引号极少(因为 Windows 下不支持),有引号也应该转义的,而且因为是 web,转义是 % 的做法,所以排除引号很稳定。 @jiejiss #27 XML 是因为可递归所以不能用正则。 |
![]() | 32 jiejiss 2020-07-05 23:16:02 +08:00 @no1xsyzy #31 可递归也不一定不能用正则的,现在很多语言的正则引擎支持很多 irregular 的 feature 比如 lookbehind 和引用,我甚至可以用正则匹配正整数域内全部 3/5/7 的倍数。甚至 perl 的正则都是图灵完备的了 关键其实在于正则有合适的使用场景,我希望的是楼主看完这篇回答能认识到正则不是万能的 |
33 supermoonie OP @no1xsyzy https://assets-1253328229.cos.ap-shanghai.myqcloud.com/assets/20200705231821.png 这点倒是提醒我了,文件名中带双引号,浏览器可能会转译,不过 Apache HttpClient 发出的请求却是 \" ,还是要处理下 |
34 supermoonie OP @jiejiss 受教了,楼猪主要从事 Java 开发,所以对前端这块不是特别熟悉,现在已经能不用正则就不用正则了 |
![]() | 35 no1xsyzy 2020-07-05 23:27:37 +08:00 @jiejiss #32 也是,重点在于不必拿正则做一切的观念,而不仅仅是具体某个问题是否适合。 不过,在当前主题下,我觉得没必要为了一行去搞个 parser,反复 split,相比之下单纯针对引号会更方便一点。 如果是大的物件的一部分,已经引入了 HTTP 相关内容还是 parser 比较好。 |
![]() | 36 no1xsyzy 2020-07-05 23:37:52 +08:00 @supermoonie #33 我的错,拍脑袋了 https://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.5.1 https://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2 这里是一个 quoted-string,转义该用的就是 \" /"((?:\.|[^"\\])*)"/g |
37 supermoonie OP @no1xsyzy 其实需求是解析 HTTP 请求中 multipart 并展示,要把每一个 formdata 中的内容都解析出来,如果不用正则的话,就要先 split('\n') 分行,然后再每一行判断是否为 Content-Disposition,然后再解析,如果用正则的话,就可以根据 Content-Disposition 关键字一步到位,最终效果如图: https://assets-1253328229.cos.ap-shanghai.myqcloud.com/assets/20200705233841.png |
38 supermoonie OP @no1xsyzy 大佬 666 啊,正则随手就来,协议链接也很有说服力,佩服佩服 |
39 supermoonie OP @no1xsyzy 最终方案: let _sub = function(str) { return [...str.matchAll(/name="([^\s]+)"/g)].map(item => item[1]); }; |
![]() | 40 MrUser 2020-07-06 09:17:52 +08:00 (?<==").*?(?=")/g JS 测试代码: 'Content-Disposition: form-data; name="test.png"; filename="test.jpg" 或 Content-Disposition: form-data; name="foo"'.match(/(?<==").*?(?=")/g) // 输出:["test.png", "test.jpg", "foo"] 规则说明:匹配双引号里边的内容,开头双引号要求是“="” |
![]() | 41 MrUser 2020-07-06 09:28:11 +08:00 正则的前置断言各浏览器支持性确实不好,收回以上回复 |
42 supermoonie OP @MrUser Safari 全军覆没。。。 |
![]() | 43 creanme 2020-07-06 21:19:27 +08:00 我朋友写了个 /(?:(?:file)?name=)"([^"]+")/g,但是没法正常输出 groups,不知道为啥。string 的 match 在有 global 标志的情况下,不会输出 groups,只会输出匹配项。 regex 的 exec 则 不管是 new Regexp('(?:(?:file)?name=)"([^"]+")','g')还是 new Regexp(/(?:(?:file)?name=)"([^"]+")/g)都没法匹配全局。 |
![]() | 44 creanme 2020-07-06 21:35:36 +08:00 想通了,exec 有个 lastindex 标志位,所以不会一次输出全局的匹配。 |
45 supermoonie OP @creanme 我已经抛弃 js 的正则了 |