grep 正则表达式仅在一行不以以下开头时才匹配
grep regex match only if a line doesn't start by
i put a test file at the bottom of this post with a expected result
我想要什么
我在文件夹中有一些文件,例如:
src
├── app
│ ├── app.controller.ts
│ ├── app.module.ts
│ ├── app.service.ts
│ └── interceptor
│ └── json-api.interceptor.ts
├── auth
│ ├── auth.controller.ts
│ ├── auth.module.ts
│ ├── auth.service.ts
│ ├── decorator
│ │ ├── auth-user.decorator.ts
│ │ ├── is-secret.decorator.ts
我想要一个脚本来检索我的 jsdoc
到这个文件中加上 jsdoc 相关函数的名称,并将结果插入到 .md
文件中。
jsdoc
始终以 /**
换行开始,并始终以 */
换行结束。
起点和终点之间的线总是以 *
开始。
在 jsdoc 的最后一行之后我们有 @
或 [A-Za-z]
。仅当模式不等于 @
.
时,我才想匹配此行
示例:
/** << start
* << the line between
*/ << end
@ xxxxxx << possible negative value
function xxxxx << possible positive value
const xxxx << possible positive value
xxxxx << possible positive value
但我不想检索以下模式:
/** something */
@ or xxxxxx
我的研究
我从 jsdoc 开始:
grep -Pro "(\/\*\*$)|(^\s+\*\s.*)|(^\s+\*\/$)" test.txt
结果还可以:
➜ grep -Pro "(\/\*\*$)|(^\s+\*\s.*)|(^\s+\*\/$)" test.txt
/**
* check if the user level is super admin
* @returns {boolean} true if the user has the right to access super admin endpoints
*/
/**
* check if the user level is super admin
* @returns {boolean} true if the user has the right to access super admin endpoints
*/
/**
* check if the user level is super admin
* @returns {boolean} true if the user has the right to access super admin endpoints
*/
现在,如果此行不是以 @
开头,我想在后面添加一行,为此我制作了这个正则表达式
((\s*)([^@]|\w)(.*))
但这根本行不通。
如果我使用否定前瞻 (\s*)(?![@])(.+)
控制台会告诉我 event not found: [@])(.+)
。
我很迷茫,如果你知道怎么做,谢谢。如果您想了解更多信息,请告诉我。
测试文件和预期结果
➜ cat test.txt
// case 1
/**
* check if the user level is super admin
* @returns {boolean} true if the user has the right to access super admin endpoints
*/
@UseGuards(AuthGuard('jwt'), LevelsGuard)
@Levels(LevelEnum.superadmin)
@Get('check/superadmin')
@ApiBearerAuth()
checkSuperAdminLevel(): boolean {
return true;
}
// case 2
/**
* check if the user level is super admin
* @returns {boolean} true if the user has the right to access super admin endpoints
*/
@Get('check/superadmin')
@ApiBearerAuth()
checkSuperAdminLevel(): boolean {
return true;
}
// case 3
/**
* check if the user level is super admin
* @returns {boolean} true if the user has the right to access super admin endpoints
*/
checkSuperAdminLevel(): boolean {
return true;
}
// case 4
/** lorem ipsum */
// case 5
lorem ipsum
预期结果
// case 1
/**
* check if the user level is super admin
* @returns {boolean} true if the user has the right to access super admin endpoints
*/
checkSuperAdminLevel(): boolean {
// case 2
/**
* check if the user level is super admin
* @returns {boolean} true if the user has the right to access super admin endpoints
*/
checkSuperAdminLevel(): boolean {
// case 3
/**
* check if the user level is super admin
* @returns {boolean} true if the user has the right to access super admin endpoints
*/
checkSuperAdminLevel(): boolean {
// case 4
nothing
// case 5
nothing
由于您使用的是 GNU grep
,因此可以进一步扩展您的正则表达式来实现您想要的效果。
首先,添加 -z
选项,它将允许将文件插入单个字符串输入(grep
模式将“看到”换行符)。
其次,您需要确保 $
锚点匹配 行 的末尾,而不仅仅是整个字符串,因此您需要 多行修饰符,(?m)
.
第三,换行符也需要匹配,以便在输出中有换行符,因此,在每个选项的末尾,您需要放置 \n?
,一个可选的换行符。
第四,由于这是一个 PCRE 模式,它将支持 \h
构造,匹配任何水平空格。当您的正则表达式可以跨行匹配时,这是一个方便的模式。注意 \s
匹配换行符,这可能会导致不受欢迎的匹配。因此,所有 \s
都替换为 \h
。
第五,由于该模式将消耗 */
行,并且您想开始寻找不以 @
开头的行,仅在该行正下方,您需要一个 positive lookbehind,一种非消耗模式。
所以,grep 命令看起来像
grep -zroP '(?m)/\*\*$\n?|^\h+\*\h.*$\n?|^\h+\*/$\n?|(?<=\*/\n)(?:\h+@.*\n)*\K.+\n?' test.txt
(?<=\*/\n)(?:\h+@.*\n)*\K.+\n?
替代方案是这样做的:
(?<=\*/\n)
- 查找紧跟在 */
和换行符 之前的位置
(?:\h+@.*\n)*
- 匹配并消耗任何零次或多次重复
\h+
- 一个或多个水平空格
@
- 一个 @
字符
.*\n
- 带有换行符 (LF) char 的行的其余部分
\K
- 匹配重置运算符,丢弃到目前为止匹配的文本从整体匹配内存缓冲区
.+
- 非空行
\n?
- 一个可选的 LF(换行符)字符。
参见regex demo。
i put a test file at the bottom of this post with a expected result
我想要什么
我在文件夹中有一些文件,例如:
src
├── app
│ ├── app.controller.ts
│ ├── app.module.ts
│ ├── app.service.ts
│ └── interceptor
│ └── json-api.interceptor.ts
├── auth
│ ├── auth.controller.ts
│ ├── auth.module.ts
│ ├── auth.service.ts
│ ├── decorator
│ │ ├── auth-user.decorator.ts
│ │ ├── is-secret.decorator.ts
我想要一个脚本来检索我的 jsdoc
到这个文件中加上 jsdoc 相关函数的名称,并将结果插入到 .md
文件中。
jsdoc
始终以 /**
换行开始,并始终以 */
换行结束。
起点和终点之间的线总是以 *
开始。
在 jsdoc 的最后一行之后我们有 @
或 [A-Za-z]
。仅当模式不等于 @
.
示例:
/** << start
* << the line between
*/ << end
@ xxxxxx << possible negative value
function xxxxx << possible positive value
const xxxx << possible positive value
xxxxx << possible positive value
但我不想检索以下模式:
/** something */
@ or xxxxxx
我的研究
我从 jsdoc 开始:
grep -Pro "(\/\*\*$)|(^\s+\*\s.*)|(^\s+\*\/$)" test.txt
结果还可以:
➜ grep -Pro "(\/\*\*$)|(^\s+\*\s.*)|(^\s+\*\/$)" test.txt
/**
* check if the user level is super admin
* @returns {boolean} true if the user has the right to access super admin endpoints
*/
/**
* check if the user level is super admin
* @returns {boolean} true if the user has the right to access super admin endpoints
*/
/**
* check if the user level is super admin
* @returns {boolean} true if the user has the right to access super admin endpoints
*/
现在,如果此行不是以 @
开头,我想在后面添加一行,为此我制作了这个正则表达式
((\s*)([^@]|\w)(.*))
但这根本行不通。
如果我使用否定前瞻 (\s*)(?![@])(.+)
控制台会告诉我 event not found: [@])(.+)
。
我很迷茫,如果你知道怎么做,谢谢。如果您想了解更多信息,请告诉我。
测试文件和预期结果
➜ cat test.txt
// case 1
/**
* check if the user level is super admin
* @returns {boolean} true if the user has the right to access super admin endpoints
*/
@UseGuards(AuthGuard('jwt'), LevelsGuard)
@Levels(LevelEnum.superadmin)
@Get('check/superadmin')
@ApiBearerAuth()
checkSuperAdminLevel(): boolean {
return true;
}
// case 2
/**
* check if the user level is super admin
* @returns {boolean} true if the user has the right to access super admin endpoints
*/
@Get('check/superadmin')
@ApiBearerAuth()
checkSuperAdminLevel(): boolean {
return true;
}
// case 3
/**
* check if the user level is super admin
* @returns {boolean} true if the user has the right to access super admin endpoints
*/
checkSuperAdminLevel(): boolean {
return true;
}
// case 4
/** lorem ipsum */
// case 5
lorem ipsum
预期结果
// case 1
/**
* check if the user level is super admin
* @returns {boolean} true if the user has the right to access super admin endpoints
*/
checkSuperAdminLevel(): boolean {
// case 2
/**
* check if the user level is super admin
* @returns {boolean} true if the user has the right to access super admin endpoints
*/
checkSuperAdminLevel(): boolean {
// case 3
/**
* check if the user level is super admin
* @returns {boolean} true if the user has the right to access super admin endpoints
*/
checkSuperAdminLevel(): boolean {
// case 4
nothing
// case 5
nothing
由于您使用的是 GNU grep
,因此可以进一步扩展您的正则表达式来实现您想要的效果。
首先,添加 -z
选项,它将允许将文件插入单个字符串输入(grep
模式将“看到”换行符)。
其次,您需要确保 $
锚点匹配 行 的末尾,而不仅仅是整个字符串,因此您需要 多行修饰符,(?m)
.
第三,换行符也需要匹配,以便在输出中有换行符,因此,在每个选项的末尾,您需要放置 \n?
,一个可选的换行符。
第四,由于这是一个 PCRE 模式,它将支持 \h
构造,匹配任何水平空格。当您的正则表达式可以跨行匹配时,这是一个方便的模式。注意 \s
匹配换行符,这可能会导致不受欢迎的匹配。因此,所有 \s
都替换为 \h
。
第五,由于该模式将消耗 */
行,并且您想开始寻找不以 @
开头的行,仅在该行正下方,您需要一个 positive lookbehind,一种非消耗模式。
所以,grep 命令看起来像
grep -zroP '(?m)/\*\*$\n?|^\h+\*\h.*$\n?|^\h+\*/$\n?|(?<=\*/\n)(?:\h+@.*\n)*\K.+\n?' test.txt
(?<=\*/\n)(?:\h+@.*\n)*\K.+\n?
替代方案是这样做的:
(?<=\*/\n)
- 查找紧跟在*/
和换行符 之前的位置
(?:\h+@.*\n)*
- 匹配并消耗任何零次或多次重复\h+
- 一个或多个水平空格@
- 一个@
字符.*\n
- 带有换行符 (LF) char 的行的其余部分
\K
- 匹配重置运算符,丢弃到目前为止匹配的文本从整体匹配内存缓冲区.+
- 非空行\n?
- 一个可选的 LF(换行符)字符。
参见regex demo。