Regex Vim:正则表达式,用于删除除以给定数字列表开头的行以外的所有行

Regex Vim:正则表达式,用于删除除以给定数字列表开头的行以外的所有行,regex,vim,regex-negation,Regex,Vim,Regex Negation,我有一个csv文件,其中除第一行外的每一行都以数字开头,如下所示: subject,parameter1,parameter2,parameter3 1,blah,blah,blah 3,blah,blah,blah 2,blah,blah,blah 44,blah,blah,blah 12,blah,blah,blah 14,blah,blah,blah 11,blah,blah,blah 10,blah,blah,blah 11,blah,blah,blah 13,blah,blah,bla

我有一个csv文件,其中除第一行外的每一行都以数字开头,如下所示:

subject,parameter1,parameter2,parameter3
1,blah,blah,blah
3,blah,blah,blah
2,blah,blah,blah
44,blah,blah,blah
12,blah,blah,blah
14,blah,blah,blah
11,blah,blah,blah
10,blah,blah,blah
11,blah,blah,blah
13,blah,blah,blah
3,blah,blah,blah
...
:g!/^[1 6 12]\|^subject/d
我想删除除第一行以外的所有行,比如说,以数字1、6、12开头的行。 我试着这样做:

subject,parameter1,parameter2,parameter3
1,blah,blah,blah
3,blah,blah,blah
2,blah,blah,blah
44,blah,blah,blah
12,blah,blah,blah
14,blah,blah,blah
11,blah,blah,blah
10,blah,blah,blah
11,blah,blah,blah
13,blah,blah,blah
3,blah,blah,blah
...
:g!/^[1 6 12]\|^subject/d
但12被解释为“1或2”,因此这也会删除以2开头的行

我遗漏了什么,最有效的方法应该是什么? 顺便说一句,我的列表不是1、6、12,而是包含多个单位数和两位数的数字。

使用全局匹配:

:v/^\(subject\|1\|6\|12\),/ delete
对于与该正则表达式不匹配的每一行,将其删除

它产生:

subject,parameter1,parameter2,parameter3
1,blah,blah,blah
12,blah,blah,blah

编辑:刚才我意识到您已经在使用全局匹配。您的错误在角色类中。它匹配其中的任何字符,而不考虑重复的字符,例如数字1、2、6和空格。您必须像我以前做的那样,在不同的分支中将它们分开。

使用全局匹配:

:v/^\(subject\|1\|6\|12\),/ delete
对于与该正则表达式不匹配的每一行,将其删除

它产生:

subject,parameter1,parameter2,parameter3
1,blah,blah,blah
12,blah,blah,blah

编辑:刚才我意识到您已经在使用全局匹配。您的错误在角色类中。它匹配其中的任何字符,而不考虑重复的字符,例如数字1、2、6和空格。您必须像我以前做的那样,在不同的分支中将它们分开。

一个“功能性”替代方案:

:g/./if index([1,12,6],str2nr(split(getline("."),",")[0]))<0|exec 'normal! dd'|endif
:g//if索引([1,12,6],str2nr(拆分(getline(“.”,“,”[0]))a“功能”替代方案:

:g/./if index([1,12,6],str2nr(split(getline("."),",")[0]))<0|exec 'normal! dd'|endif

:g//if索引([1,12,6],str2nr(split(getline(“.”,“,”[0]))字符类
[1 6 12]
表示“该类中的任何单个字符,
i、 e.
”、1、2、6
中的任何一个(重复的
1
被忽略)

你可以用

:g!/^1,\|^6,\|^12,\|^subject/d
这与您的原始语法非常接近,但它可以工作(在Mac OS X上使用vim进行测试)

注意-必须包含逗号,以便以1开头的
行不会“保护”
11
12345

不过,您可能希望使用
grep
以不同的方式执行此操作

将所有“白名单”编号放在一个文件中,每行一个,如下所示:

^subject
^1,
^2,
^6,
^12,
那就做吧

grep -f whitelist csvFile
输出将是您的“编辑”文件(您可以通过管道将其传输到新文件)

如果你对“效率”更感兴趣,你可以让你的文本文件(我们继续称它为
白名单
)仅仅

并使用以下命令:

cat whitelist | xargs -I {} grep "^"{}"," cvsFile
这需要解释一下

xargs            - take the input one line at a time
-I {}            - and insert that line in the command that follows, at the {}
这意味着grep命令将运行
n
次(在白名单文件中每行运行一次),并且每次馈入
grep
的正则表达式都是

"^"              - start of line
{}               - contents of one line of the input file (whitelist)
","              - comma that follows the number
这是一种简洁的写作方式

grep "^subject," csvFile; grep "^1," csvFile; grep "^2," csvFile; 
等等


它的优点是,您现在可以按任何方式生成白名单-只要它最终出现在一个文件中,一次一行,您就可以使用它;缺点是您实际上正在运行grep n次。如果您的文件变得非常大,并且白名单中有大量项目,这可能会开始成为一个问题;但是您的操作系统可能会在第一次读取后将文件放入缓存,速度非常快。使用
^
锚定使正则表达式非常高效-一旦找不到匹配项,它就会转到下一行。

字符类
[1 6 12]
表示“该类中的任何单个字符,
i、 e.
”、1、2、6
中的任何一个(重复的
1
被忽略)

你可以用

:g!/^1,\|^6,\|^12,\|^subject/d
这与您的原始语法非常接近,但它可以工作(在Mac OS X上使用vim进行测试)

注意-必须包含逗号,以便以1开头的
行不会“保护”
11
12345

不过,您可能希望使用
grep
以不同的方式执行此操作

将所有“白名单”编号放在一个文件中,每行一个,如下所示:

^subject
^1,
^2,
^6,
^12,
那就做吧

grep -f whitelist csvFile
输出将是您的“编辑”文件(您可以通过管道将其传输到新文件)

如果你对“效率”更感兴趣,你可以让你的文本文件(我们继续称它为
白名单
)仅仅

并使用以下命令:

cat whitelist | xargs -I {} grep "^"{}"," cvsFile
这需要解释一下

xargs            - take the input one line at a time
-I {}            - and insert that line in the command that follows, at the {}
这意味着grep命令将运行
n
次(在白名单文件中每行运行一次),并且每次馈入
grep
的正则表达式都是

"^"              - start of line
{}               - contents of one line of the input file (whitelist)
","              - comma that follows the number
这是一种简洁的写作方式

grep "^subject," csvFile; grep "^1," csvFile; grep "^2," csvFile; 
等等


它的优点是,你现在可以以任何方式生成你的白名单——只要它最终出现在一个文件中,一次一行,你就可以使用它;缺点是您实际上正在运行grep n次。如果您的文件变得非常大,并且您的白名单中有大量项目,这可能会开始成为一个问题;但由于您的操作系统可能会在第一次读取后将文件放入缓存,因此速度非常快。使用
^
锚定使正则表达式非常高效-一旦找不到匹配项,它就会转到下一行。

顺便说一句,
:v
:g!的同义词
.BTW,
:v
:g。希望我能投票支持grep技巧,但我的票数不够reputation@geo909-我很乐意接受你的赞扬,而不是一票!我希望我能投格雷普的一票,但是票数不够reputation@geo909-我很乐意接受你的赞扬,而不是一票!