我有一个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,我的列表包含许多单个和2位数字。
答案 0 :(得分:3)
“功能性”替代方案:
:g/./if index([1,12,6],str2nr(split(getline("."),",")[0]))<0|exec 'normal! dd'|endif
答案 1 :(得分:3)
字符类[1 6 12]
表示“此类中的任何单个字符,
即' ', 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
的正则表达式将是1}的串联
"^" - 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次。如果您的文件变得非常大,并且白名单中有大量项目,那么这可能会成为一个问题;但由于您的操作系统可能会在第一次读取后将文件放入缓存中,因此它非常快。 ^
锚点的使用使得正则表达式非常有效 - 只要它找不到匹配就会转到下一行。
答案 2 :(得分:2)
使用全局匹配:
:v/^\(subject\|1\|6\|12\),/ delete
对于与该正则表达式不匹配的每一行,请将其删除。
它产生:
subject,parameter1,parameter2,parameter3
1,blah,blah,blah
12,blah,blah,blah
编辑:刚才我意识到你已经在使用全局匹配了。你的错误是在角色类中。它匹配其中的任何字符而不管重复的字符,在您的情况下编号为一,二,六和一个空格。你必须像以前一样在不同的分支中分开它们。