替换所有出现的字符,除非被两个不同的模式包围
Replace all occurances of a character unless surrounded by two different patterns
我想找到一个正则表达式(最好是在 perl 中,但任何风格都可以)来替换每个 _
除了前面正好是 8 位数字 和 后跟恰好 6 位数字。
实际上,我想替换文件名中的 _
除了那些格式为 YYYYMMDD_hhmmss
.
的日期
一般来说,我想替换某些字符的所有出现,这些字符 前面没有某种模式 和 后面没有其他模式.
我尝试了很多正则表达式并在网上查找了很多,但我没有找到任何东西!
我知道可以用 .
替换每个 _
,然后在 YYYYMMDD.hhmmss
中恢复 _
,但我有兴趣一步完成(希望这是可能的)。
以下是一些替换示例:
Patate_17890505_TitreEnCamelCase.ext --> Patate.17890505.TitreEnCamelCase.ext
EPFL_AlgebreLineaire --> EPFL.AlgebreLineaire
ipe.20210302_005606.pdf --> ipe.20210302_005606.pdf
1_ --> 1.
12_ --> 12.
_1 --> .1
_12 --> .12
12345678_ --> 12345678.
_123456 --> .123456
12345678_12345 --> 12345678.12345
1234567_123456 --> 1234567.123456
1234567_12345 --> 1234567.12345
123456_12345 --> 123456.12345
12345678_1234567 --> 12345678.1234567
123456789_123456 --> 123456789.123456
123456789_1234567 --> 123456789.1234567
_patate__truc__ --> .patate..truc..
___ --> ...
foo_12345678 --> foo.12345678
foo_12345678_123456_bar --> foo.12345678_123456.bar
12345678_123456 --> 12345678_123456
foo12345678_123456bar --> foo12345678_123456bar
下面是我试过的几个例子。
与我想要的完全相反,即替换每个_
前面恰好8位数字和后面恰好6位数字(在[=37上尝试=]):
s/((?<!\d)(?:\d{8}))_((?:\d{6})(?!\d))/./g
它有效,所以我需要这个正则表达式的否定…
只是消极的后视和消极的前瞻(在 regex101 上尝试):
s/(?<!\d{8})_(?!\d{6})/./g
失败:如果 _
前面正好有 8 位数字 或 后面正好有 6 位数字,则不会替换,例如 _
在这些字符串中未被替换:
12345678_
_123456
12345678_12345
1234567_123456
我需要替换除“and”之外的所有内容,但是这个替换了除“or”之外的所有内容(所以它遗漏了一些_
)。
灵感来自 this answer (from python regex: match a char surrounded by exactly 2 chars) (try it on regex101):
s/(?<!(?<!\d)\d{8})_(?!\d{6}(?!\d))/./g
失败:同上一个原因。
原始答案中的正则表达式有效,因为它替换了字符 前面有一个预模式 和 后跟 post-模式.
灵感来自 this answer (from Replace character UNLESS surrounded by specific tag), but I do not really understand how it works (try it on regex101):
s/_(?:(?!(?:.*?\d{6}))|(?=[^\d]+\d{8}))/./g
失败:在这些示例中,_
未被替换
_123456
1234567_123456
12345678_1234567
123456789_123456
123456789_1234567
foo_12345678
原来的问题和我的很接近,但是不是\d{8}
和\d{6}
,pre-pattern和post-pattern是HTML标签,所以问题更简单:<tag>
和 </tag>
是独特的元素,对于我的问题,post-模式 \d{6}
后面可以跟另一个数字(同样是预模式\d{8}
前面可以有其他数字)。
但是这个几乎可以工作,与之前的尝试不同,它替换了这两个字符串中的 _
:
12345678_
12345678_12345
所以也许修改可以使它按我想要的方式工作......
您可以使用
(?<!\d)\d{8}_\d{6}(?!\d)(*SKIP)(*F)|_
参见regex demo。 详情:
(?<!\d)\d{8}_\d{6}(?!\d)
- 八位数字,_
和不包含任何其他数字的六位数字
(*SKIP)(*F)
- 在当前位置匹配失败并从失败位置继续正则表达式搜索
|
- 或
_
- 任何其他上下文中的下划线。
另一种正则表达式是
_(?!(?<=(?<!\d)\d{8}_)\d{6}(?!\d))
参见 this regex demo。 详情:
_
- 下划线
(?!(?<=(?<!\d)\d{8}_)\d{6}(?!\d))
- 如果在当前位置的右侧 - 有六位(且不超过六位)紧接八位数字和下划线的数字,则匹配失败的否定前瞻。
我想找到一个正则表达式(最好是在 perl 中,但任何风格都可以)来替换每个 _
除了前面正好是 8 位数字 和 后跟恰好 6 位数字。
实际上,我想替换文件名中的 _
除了那些格式为 YYYYMMDD_hhmmss
.
的日期
一般来说,我想替换某些字符的所有出现,这些字符 前面没有某种模式 和 后面没有其他模式.
我尝试了很多正则表达式并在网上查找了很多,但我没有找到任何东西!
我知道可以用 .
替换每个 _
,然后在 YYYYMMDD.hhmmss
中恢复 _
,但我有兴趣一步完成(希望这是可能的)。
以下是一些替换示例:
Patate_17890505_TitreEnCamelCase.ext --> Patate.17890505.TitreEnCamelCase.ext
EPFL_AlgebreLineaire --> EPFL.AlgebreLineaire
ipe.20210302_005606.pdf --> ipe.20210302_005606.pdf
1_ --> 1.
12_ --> 12.
_1 --> .1
_12 --> .12
12345678_ --> 12345678.
_123456 --> .123456
12345678_12345 --> 12345678.12345
1234567_123456 --> 1234567.123456
1234567_12345 --> 1234567.12345
123456_12345 --> 123456.12345
12345678_1234567 --> 12345678.1234567
123456789_123456 --> 123456789.123456
123456789_1234567 --> 123456789.1234567
_patate__truc__ --> .patate..truc..
___ --> ...
foo_12345678 --> foo.12345678
foo_12345678_123456_bar --> foo.12345678_123456.bar
12345678_123456 --> 12345678_123456
foo12345678_123456bar --> foo12345678_123456bar
下面是我试过的几个例子。
与我想要的完全相反,即替换每个_
前面恰好8位数字和后面恰好6位数字(在[=37上尝试=]):
s/((?<!\d)(?:\d{8}))_((?:\d{6})(?!\d))/./g
它有效,所以我需要这个正则表达式的否定…
只是消极的后视和消极的前瞻(在 regex101 上尝试):
s/(?<!\d{8})_(?!\d{6})/./g
失败:如果 _
前面正好有 8 位数字 或 后面正好有 6 位数字,则不会替换,例如 _
在这些字符串中未被替换:
12345678_
_123456
12345678_12345
1234567_123456
我需要替换除“and”之外的所有内容,但是这个替换了除“or”之外的所有内容(所以它遗漏了一些_
)。
灵感来自 this answer (from python regex: match a char surrounded by exactly 2 chars) (try it on regex101):
s/(?<!(?<!\d)\d{8})_(?!\d{6}(?!\d))/./g
失败:同上一个原因。
原始答案中的正则表达式有效,因为它替换了字符 前面有一个预模式 和 后跟 post-模式.
灵感来自 this answer (from Replace character UNLESS surrounded by specific tag), but I do not really understand how it works (try it on regex101):
s/_(?:(?!(?:.*?\d{6}))|(?=[^\d]+\d{8}))/./g
失败:在这些示例中,_
未被替换
_123456
1234567_123456
12345678_1234567
123456789_123456
123456789_1234567
foo_12345678
原来的问题和我的很接近,但是不是\d{8}
和\d{6}
,pre-pattern和post-pattern是HTML标签,所以问题更简单:<tag>
和 </tag>
是独特的元素,对于我的问题,post-模式 \d{6}
后面可以跟另一个数字(同样是预模式\d{8}
前面可以有其他数字)。
但是这个几乎可以工作,与之前的尝试不同,它替换了这两个字符串中的 _
:
12345678_
12345678_12345
所以也许修改可以使它按我想要的方式工作......
您可以使用
(?<!\d)\d{8}_\d{6}(?!\d)(*SKIP)(*F)|_
参见regex demo。 详情:
(?<!\d)\d{8}_\d{6}(?!\d)
- 八位数字,_
和不包含任何其他数字的六位数字(*SKIP)(*F)
- 在当前位置匹配失败并从失败位置继续正则表达式搜索|
- 或_
- 任何其他上下文中的下划线。
另一种正则表达式是
_(?!(?<=(?<!\d)\d{8}_)\d{6}(?!\d))
参见 this regex demo。 详情:
_
- 下划线(?!(?<=(?<!\d)\d{8}_)\d{6}(?!\d))
- 如果在当前位置的右侧 - 有六位(且不超过六位)紧接八位数字和下划线的数字,则匹配失败的否定前瞻。