我有以下测试文件名:
abc001_20111104_summary_123.txt
abc008_200700953_timeline.txt
abc008_20080402_summary200201573unitf.txt
123456.txt
100101-100102 test.txt
abc008_20110902_summary200110254.txt
abcd 200601141 summary.txt
abc008_summary_200502169_xyz.txt
我需要从每个文件名中提取数字。
该号码必须 6,7,9或10位长(因此,不包括8位号码)。
我想获得第一个数字,如果找到多个,或者如果没有找到则返回空字符串。
我设法在 2个步骤中执行此操作,首先删除8位数字,然后从列表中提取6到10位数字。
step 1
regex: ([^0-9])([0-9]{8})([^0-9])
replacement: \1\3
step 2
regex: (.*?)([1-9]([0-9]{5,6}|[0-9]{8,9}))([^0-9].*)
replacement: \2
我在这两个步骤之后得到的数字正是我正在寻找的:
[]
[200700953]
[200201573]
[123456]
[100101]
[200110254]
[200601141]
[200502169]
现在,问题是: 有没有办法一步完成?
我见过this nice solution一个类似的问题,然而,如果发现不止一个,它会给我最新的数字。
注意:使用The Regex Coach进行测试。
答案 0 :(得分:7)
假设你的正则表达式引擎支持lookbehind断言:
(?<!\d)\d{6}(?:\d?|\d{3,4})(?!\d)
<强>解释强>
(?<!\d) # Assert that the previous character (if any) isn't a digit
\d{6} # Match 6 digits
(?: # Either match
\d? # 0 or 1 digits
| # or
\d{3,4} # 3 or 4 digits
) # End of alternation
(?!\d) # Assert that the next character (if any) isn't a digit
答案 1 :(得分:0)
试试这个:
regex: /(?:^|\D)(\d{6}(?:\d(?:\d{2,3})?)?)(?:\D|$)/
replacement: \1
这将提取六位数字,可选地后跟一位数字(总共7位),可选地接着输入2或3位数(9或10)。
答案 2 :(得分:0)
$subject = "abc001_20111104_summary_123.txt";
$subject ="abc008_200700953_timeline.txt";
$subject ="abc008_20080402_summary200201573unitf.txt";
$subject ="123456.txt"
$subject ="100101-100102 test.txt"
$subject ="abc008_20110902_summary200110254.txt";
$subject ="abcd 200601141 summary.txt";
$subject ="abc008_summary_200502169_xyz.txt";
$pattern = '*(?<!\d)(\d{6,7}|\d{9,10})(?!\d)*';
preg_match_all($pattern, $subject, $matches);
print_r($matches);
您获得了预期的结果:
答案 3 :(得分:0)
匹配[0-9]{6,7}|[0-9]{9,10}
边缘的单词边界或非数字应该这样做:
([^0-9]|\<)([0-9]{6,7}|[0-9]{9,10})([^0-9]|\>)