[英]Vim: regular expression to delete all lines except those starting with a given list of numbers
我有一个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
...
我想删除除以数字1,6,12开头的第一行以外的所有行。 我正在尝试这样的事情:
:g!/^[1 6 12]\|^subject/d
但是12被解释为“ 1或2”,因此这也会删除以2开头的行。
我缺少什么,最有效的方法应该是什么? 顺便说一句,而不是1、6、12,我的列表包含许多单个数字和两位数字。
一种“功能性”替代方案:
:g/./if index([1,12,6],str2nr(split(getline("."),",")[0]))<0|exec 'normal! dd'|endif
字符类别[1 6 12]
表示“此类中的任何单个字符,
即' ', 1, 2, 6
1、2、6中的任何一个(重复的1
被忽略)。
你可以用
:g!/^1,\|^6,\|^12,\|^subject/d
这与您的原始语法非常接近-但可以使用(在Mac OS X上用vim测试)。
注-包括逗号是很重要的,因此, line starting with 1
不“保护” 11
, 12345
等。
您可能希望通过grep
来执行其他操作。
将所有“白名单中的”数字放在文件中,每行一个,如下所示:
^subject
^1,
^2,
^6,
^12,
然后做
grep -f whitelist csvFile
输出将是您的“已编辑”文件(您可以通过管道将其传输到新文件)。
如果您对“效率”更感兴趣,可以将您的文本文件(让我们继续将其称为whitelist
)
subject
1
2
6
12
并使用以下命令:
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/^\(subject\|1\|6\|12\),/ delete
对于与该正则表达式不匹配的每一行,将其删除。
它产生:
subject,parameter1,parameter2,parameter3
1,blah,blah,blah
12,blah,blah,blah
编辑 :刚才我意识到您已经在使用全局匹配。 您的错误是在字符类中。 它与其中的任何字符匹配,而与重复字符无关,在您的情况下为一,二,六和一个空格。 您必须像以前一样将它们分隔在不同的分支中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.