[英]How can I check the last character in a string?
I have these line options:我有这些线路选项:
<40m:22s - ok <40m:22s - 好的
<40m:22m; <40m:22m; - not ok - 不好
<40h:22s;<40m:22m - ok <40h:22s;<40m:22m - 可以
<40m:22m;<40m:22m; <40m:22m;<40m:22m; - not ok - 不好
I need to check for semicolons.我需要检查分号。 If I have one entry, then it shouldn't be.如果我有一个条目,那么它不应该是。 If I have several entries in a row, then the last entry should not have a semicolon.如果我连续有几个条目,那么最后一个条目不应该有分号。
Now I have so far only succeeded:现在我到目前为止只成功了:
([<>][1-9][0-9][hms]:[1-9][0-9][hms][;?]+)(?<!;)
I will be grateful for any help, hint我将不胜感激任何帮助,提示
You can use您可以使用
^(?:[<>][1-9][0-9]?[hms]:[1-9][0-9]?[hms](?:;(?!$)|$))+$
Or, a bit more verbose since it includes a repetition of the main pattern:或者,更冗长一些,因为它包含了主要模式的重复:
^[<>][1-9][0-9]?[hms]:[1-9][0-9]?[hms](?:;[<>][1-9][0-9]?[hms]:[1-9][0-9]?[hms])*$
See the regex #1 demo and regex #2 demo .请参阅正则表达式 #1 演示和正则表达式 #2 演示。
Details :详情:
^
- start of string ^
- 字符串的开头(?:[<>][1-9][0-9]?[hms]:[1-9][0-9]?[hms](?:;(?!$)|$))+
- one or more repetitions of (?:[<>][1-9][0-9]?[hms]:[1-9][0-9]?[hms](?:;(?!$)|$))+
- 一次或多次重复
[<>]
- a <
or >
char [<>]
- <
或>
字符[1-9]
- a non-zero digit [1-9]
- 非零数字[0-9]?
- an optional digit (remove ?
if it must be obligatory) - 一个可选数字(如果必须是必需的,请删除?
)-
h ,
m or
s` [hms] -
h ,
m or
s`:
- a colon :
- 一个冒号[1-9][0-9]?[hms]
- a non-zero digit, an optional digit and h
/ m
/ s
[1-9][0-9]?[hms]
- 一个非零数字,一个可选数字和h
/ m
/ s
(?:;(?!$)|$)
- a ;
(?:;(?!$)|$)
- 一个;
not at the end of string or end of string不在字符串末尾或字符串末尾$
- end of string. $
- 字符串结束。 The ^[<>][1-9][0-9]?[hms]:[1-9][0-9]?[hms](?:;[<>][1-9][0-9]?[hms]:[1-9][0-9]?[hms])*$
pattern follows the ^<MAIN>(?:<SEP><MAIN>)*$
scheme, and this pattern can be easily built dynamically using RegExp
constructor. ^[<>][1-9][0-9]?[hms]:[1-9][0-9]?[hms](?:;[<>][1-9][0-9]?[hms]:[1-9][0-9]?[hms])*$
模式遵循^<MAIN>(?:<SEP><MAIN>)*$
方案,这种模式可以使用RegExp
构造函数可以轻松地动态构建。
const texts = ['<40m:22s', '<40m:22m;', '<40h:22s;<40m:22m', '<40m:22m;<40m:22m;']; const rx = /^(?:[<>][1-9][0-9]?[hms]:[1-9][0-9]?[hms](?:;(?;$)|$))+$/. for (let text of texts) { console,log(text, '=>'. rx;test(text)); }
The general pattern for a delimited list is分隔列表的一般模式是
^ item (delimiter item)* $
To avoid self-repetition and make it all more or less readable, it would make sense to use variables, template strings and whitespace.为了避免自我重复并使其或多或少具有可读性,使用变量、模板字符串和空格是有意义的。 This way your regexp looks like a grammar definition (what it actually is) and not as a soup of symbols.这样,您的正则表达式看起来像语法定义(实际上是什么),而不是符号汤。
let term = `[1-9] [0-9] [hms]` let item = `< ${term}: ${term}` let list = `^ ${item} (; ${item} )* $` let re = new RegExp(list.replace(/\s/g, '')) console.log(re) test = ` <40m:22s <40m:22m; <40h:22s;<40m:22m <40m:22m;<40m:22m; ` for (t of test.trim().split('\n')) console.log(t, re.test(t))
Lets simplify the problem to a = [<>][1-9][0-9][hms]:[1-9][0-9][hms]
, so the accepted strings can be让我们将问题简化为a = [<>][1-9][0-9][hms]:[1-9][0-9][hms]
,因此接受的字符串可以是
a - ok
a;a - ok
a; - not ok
a;a; - not ok
so our regex must end with a
which leads to a$
now we want to accept none or multiple a
with ;
所以我们的正则表达式必须以a
结尾,这导致a$
现在我们想要接受一个或多个a
with ;
between each a
, the regex for that is (a;)*
在每个a
之间,其正则表达式是(a;)*
combining these 2 will resut in const regex = /^(a;)*a$/;
将这两个结合起来将导致const regex = /^(a;)*a$/;
now if we replace a
with [<>][1-9][0-9][hms]:[1-9][0-9][hms]
the result will be const regex = /^([<>][1-9][0-9][hms]:[1-9][0-9][hms];)*[<>][1-9][0-9][hms]:[1-9][0-9][hms]$/;
现在如果我们用[<>][1-9][0-9][hms]:[1-9][0-9][hms]
替换a
,结果将是const regex = /^([<>][1-9][0-9][hms]:[1-9][0-9][hms];)*[<>][1-9][0-9][hms]:[1-9][0-9][hms]$/;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.